Index: src/Makefile.inc1 =================================================================== RCS file: /home/ncvs/src/Makefile.inc1,v retrieving revision 1.141.2.45 diff -u -u -r1.141.2.45 Makefile.inc1 --- src/Makefile.inc1 28 Apr 2002 19:59:27 -0000 1.141.2.45 +++ src/Makefile.inc1 1 Jul 2002 19:42:17 -0000 @@ -743,6 +743,7 @@ # libskey libtacplus libutil libz libssh # libradius: libmd # libreadline: libncurses +# libssh: libcrypto libz # libskey: libcrypt libmd # libstc++: msun # libtacplus: libmd @@ -764,7 +765,7 @@ .endif .if !defined(NOSECURE) && !defined(NOCRYPT) -_secure_lib= secure/lib +_secure_lib= secure/lib/libcrypto secure/lib/libssh secure/lib .endif .if !defined(NOCRYPT) && defined(MAKE_KERBEROS4) @@ -785,10 +786,10 @@ libraries: .for _lib in ${_csu} gnu/lib/csu gnu/lib/libgcc lib/libmd lib/libcrypt \ - ${_secure_lib} ${_kerberosIV_lib} \ + lib/libz ${_secure_lib} ${_kerberosIV_lib} \ ${_kerberos5_lib} lib/libcom_err lib/msun lib/libncurses \ lib/libopie lib/libradius lib/libskey lib/libtacplus lib/libutil \ - lib/libz lib gnu/lib ${_libperl} usr.bin/lex/lib ${_libkeycap} + lib gnu/lib ${_libperl} usr.bin/lex/lib ${_libkeycap} .if exists(${.CURDIR}/${_lib}) cd ${.CURDIR}/${_lib}; \ ${MAKE} depend; \ Index: src/crypto/openssh/CREDITS =================================================================== RCS file: src/crypto/openssh/CREDITS diff -N src/crypto/openssh/CREDITS --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/CREDITS 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,94 @@ +Tatu Ylonen - Creator of SSH + +Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, +Theo de Raadt, and Dug Song - Creators of OpenSSH + +Alain St-Denis - Irix fix +Alexandre Oliva - AIX fixes +Andre Lucas - new login code, many fixes +Andreas Steinmetz - Shadow password expiry support +Andrew McGill - SCO fixes +Andrew Morgan - PAM bugfixes +Andrew Stribblehill - Bugfixes +Andy Sloane - bugfixes +Aran Cox - SCO bugfixes +Arkadiusz Miskiewicz - IPv6 compat fixes +Ben Lindstrom - NeXT support +Ben Taylor - Solaris debugging and fixes +Bratislav ILICH - Configure fix +Charles Levert - SunOS 4 & bug fixes +Chip Salzenberg - Assorted patches +Chris Adams - OSF SIA support +Chris Saia - SuSE packaging +Chris, the Young One - Password auth fixes +Christos Zoulas - Autoconf fixes +Chun-Chung Chen - RPM fixes +Corinna Vinschen - Cygwin support +Dan Brosemer - Autoconf support, build fixes +Darren Hall - AIX patches +Darren Tucker - AIX BFF package scripts +David Agraz - Build fixes +David Del Piero - bug fixes +David Hesprich - Configure fixes +David Rankin - libwrap, AIX, NetBSD fixes +Ed Eden - configure fixes +Garrick James - configure fixes +Gary E. Miller - SCO support +Ged Lodder - HPUX fixes and enhancements +Gert Doering - bug and portability fixes +HARUYAMA Seigo - Translations & doc fixes +Hideaki YOSHIFUJI - IPv6 and bug fixes +Hiroshi Takekawa - Configure fixes +Holger Trapp - KRB4/AFS config patch +IWAMURO Motonori - bugfixes +Jani Hakala - Patches +Jarno Huuskonen - Bugfixes +Jim Knoble - Many patches +Jonchen (email unknown) - the original author of PAM support of SSH +Juergen Keil - scp bugfixing +KAMAHARA Junzo - Configure fixes +Kees Cook - scp fixes +Kenji Miyake - Configure fixes +Kevin O'Connor - RSAless operation +Kevin Steves - HP support, bugfixes, improvements +Kiyokazu SUTO - Bugfixes +Larry Jones - Bugfixes +Lutz Jaenicke - Bugfixes +Marc G. Fournier - Solaris patches +Mark D. Baushke - bug fixes +Martin Johansson - Linux fixes +Mark D. Roth - Features, bug fixes +Mark Miller - Bugfixes +Matt Richards - AIX patches +Michael Stone - Irix enhancements +Nakaji Hiroyuki - Sony News-OS patch +Nalin Dahyabhai - PAM environment patch +Nate Itkin - SunOS 4.1.x fixes +Niels Kristian Bech Jensen - Assorted patches +Pavel Kankovsky - Security fixes +Pavel Troller - Bugfixes +Pekka Savola - Bugfixes +Peter Kocks - Makefile fixes +Phil Hands - Debian scripts, assorted patches +Phil Karn - Autoconf fixes +Philippe WILLEM - Bugfixes +Phill Camp - login code fix +Rip Loomis - Solaris package support, fixes +SAKAI Kiyotaka - Multiple bugfixes +Simon Wilkinson - PAM fixes, Compat with MIT KrbV +Svante Signell - Bugfixes +Thomas Neumann - Shadow passwords +Tim Rice - Portability & SCO fixes +Tobias Oetiker - Bugfixes +Tom Bertelson's - AIX auth fixes +Tor-Ake Fransson - AIX support +Tudor Bosman - MD5 password support +Udo Schweigert - ReliantUNIX support +Zack Weinberg - GNOME askpass enhancement + +Apologies to anyone I have missed. + +Damien Miller + +$Id$ + Index: src/crypto/openssh/ChangeLog =================================================================== RCS file: src/crypto/openssh/ChangeLog diff -N src/crypto/openssh/ChangeLog --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ChangeLog 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,1170 @@ +20020626 + - (stevesk) [monitor.c] remove duplicate proto15 dispatch entry for PAM + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/06/23 21:34:07 + [channels.c] + tcode is u_int + - markus@cvs.openbsd.org 2002/06/24 13:12:23 + [ssh-agent.1] + the socket name contains ssh-agent's ppid; via mpech@ from form@ + - markus@cvs.openbsd.org 2002/06/24 14:33:27 + [channels.c channels.h clientloop.c serverloop.c] + move channel counter to u_int + - markus@cvs.openbsd.org 2002/06/24 14:55:38 + [authfile.c kex.c ssh-agent.c] + cat to (void) when output from buffer_get_X is ignored + - itojun@cvs.openbsd.org 2002/06/24 15:49:22 + [msg.c] + printf type pedant + - deraadt@cvs.openbsd.org 2002/06/24 17:57:20 + [sftp-server.c sshpty.c] + explicit (u_int) for uid and gid + - markus@cvs.openbsd.org 2002/06/25 16:22:42 + [authfd.c] + unnecessary cast + - markus@cvs.openbsd.org 2002/06/25 18:51:04 + [sshd.c] + lightweight do_setusercontext after chroot() + - (bal) Updated AIX package build. Patch by dtucker@zip.com.au + - (tim) [Makefile.in] fix test on installing ssh-rand-helper.8 + - (bal) added back in error check for mmap(). I screwed up, Pointed + out by stevesk@ + - (tim) [README.privsep] UnixWare tip no longer needed. + - (bal) fixed NeXTStep missing munmap() issue. It defines HAVE_MMAP, + but it all damned lies. + - (stevesk) [README.privsep] more for sshd pseudo-account. + - (tim) [contrib/caldera/openssh.spec] add support for privsep + - (djm) setlogin needs pgid==pid on BSD/OS; from itojun@ + - (djm) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/06/26 08:53:12 + [bufaux.c] + limit size of BNs to 8KB; ok provos/deraadt + - markus@cvs.openbsd.org 2002/06/26 08:54:18 + [buffer.c] + limit append to 1MB and buffers to 10MB + - markus@cvs.openbsd.org 2002/06/26 08:55:02 + [channels.c] + limit # of channels to 10000 + - markus@cvs.openbsd.org 2002/06/26 08:58:26 + [session.c] + limit # of env vars to 1000; ok deraadt/djm + - deraadt@cvs.openbsd.org 2002/06/26 13:20:57 + [monitor.c] + be careful in mm_zalloc + - deraadt@cvs.openbsd.org 2002/06/26 13:49:26 + [session.c] + disclose less information from environment files; based on input + from djm, and dschultz@uclink.Berkeley.EDU + - markus@cvs.openbsd.org 2002/06/26 13:55:37 + [auth2-chall.c] + make sure # of response matches # of queries, fixes int overflow; + from ISS + - markus@cvs.openbsd.org 2002/06/26 13:56:27 + [version.h] + 3.4 + - (djm) Require krb5 devel for RPM build w/ KrbV + - (djm) Improve PAMAuthenticationViaKbdInt text from Nalin Dahyabhai + + - (djm) Update spec files for release + - (djm) Fix int overflow in auth2-pam.c, similar to one discovered by ISS + - (djm) Release 3.4p1 + +20020625 + - (stevesk) [INSTALL acconfig.h configure.ac defines.h] remove --with-rsh + - (stevesk) [README.privsep] minor updates + - (djm) Create privsep directory and warn if privsep user is missing + during make install + - (bal) Started list of PrivSep issues in TODO + - (bal) if mmap() is substandard, don't allow compression on server side. + Post 'event' we will add more options. + - (tim) [contrib/caldera/openssh.spec] Sync with Caldera + - (bal) moved aix_usrinfo() and noted not setting real TTY. Patch by + dtucker@zip.com.au + - (tim) [acconfig.h configure.ac sshd.c] BROKEN_FD_PASSING fix from Markus + for Cygwin, Cray, & SCO + +20020624 + - OpenBSD CVS Sync + - deraadt@cvs.openbsd.org 2002/06/23 03:25:50 + [tildexpand.c] + KNF + - deraadt@cvs.openbsd.org 2002/06/23 03:26:19 + [cipher.c key.c] + KNF + - deraadt@cvs.openbsd.org 2002/06/23 03:30:58 + [scard.c ssh-dss.c ssh-rsa.c sshconnect.c sshconnect2.c sshd.c sshlogin.c + sshpty.c] + various KNF and %d for unsigned + - deraadt@cvs.openbsd.org 2002/06/23 09:30:14 + [sftp-client.c sftp-client.h sftp-common.c sftp-int.c sftp-server.c + sftp.c] + bunch of u_int vs int stuff + - deraadt@cvs.openbsd.org 2002/06/23 09:39:55 + [ssh-keygen.c] + u_int stuff + - deraadt@cvs.openbsd.org 2002/06/23 09:46:51 + [bufaux.c servconf.c] + minor KNF. things the fingers do while you read + - deraadt@cvs.openbsd.org 2002/06/23 10:29:52 + [ssh-agent.c sshd.c] + some minor KNF and %u + - deraadt@cvs.openbsd.org 2002/06/23 20:39:45 + [session.c] + compression_level is u_int + - deraadt@cvs.openbsd.org 2002/06/23 21:06:13 + [sshpty.c] + KNF + - deraadt@cvs.openbsd.org 2002/06/23 21:06:41 + [channels.c channels.h session.c session.h] + display, screen, row, col, xpixel, ypixel are u_int; markus ok + - deraadt@cvs.openbsd.org 2002/06/23 21:10:02 + [packet.c] + packet_get_int() returns unsigned for reason & seqnr + - (bal) Also fixed IPADDR_IN_DISPLAY case where display, screen, row, col, + xpixel are u_int. + + +20020623 + - (stevesk) [configure.ac] bug #255 LOGIN_NEEDS_UTMPX for AIX. + - (bal) removed GNUism for getops in ssh-agent since glibc lacks optreset. + - (bal) add extern char *getopt. Based on report by dtucker@zip.com.au + - OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2002/06/22 02:00:29 + [ssh.h] + correct comment + - stevesk@cvs.openbsd.org 2002/06/22 02:40:23 + [ssh.1] + section 5 not 4 for ssh_config + - naddy@cvs.openbsd.org 2002/06/22 11:51:39 + [ssh.1] + typo + - stevesk@cvs.openbsd.org 2002/06/22 16:32:54 + [sshd.8] + add /var/empty in FILES section + - stevesk@cvs.openbsd.org 2002/06/22 16:40:19 + [sshd.c] + check /var/empty owner mode; ok provos@ + - stevesk@cvs.openbsd.org 2002/06/22 16:41:57 + [scp.1] + typo + - stevesk@cvs.openbsd.org 2002/06/22 16:45:29 + [ssh-agent.1 sshd.8 sshd_config.5] + use process ID vs. pid/PID/process identifier + - stevesk@cvs.openbsd.org 2002/06/22 20:05:27 + [sshd.c] + don't call setsid() if debugging or run from inetd; no "Operation not + permitted" errors now; ok millert@ markus@ + - stevesk@cvs.openbsd.org 2002/06/22 23:09:51 + [monitor.c] + save auth method before monitor_reset_key_state(); bugzilla bug #284; + ok provos@ + +20020622 + - (djm) Update README.privsep; spotted by fries@ + - (djm) Release 3.3p1 + - (bal) getopt now can be staticly compiled on those platforms missing + optreset. Patch by binder@arago.de + +20020621 + - (djm) Sync: + - djm@cvs.openbsd.org 2002/06/21 05:50:51 + [monitor.c] + Don't initialise compression buffers when compression=no in sshd_config; + ok Niels@ + - ID sync for auth-passwd.c + - (djm) Warn and disable compression on platforms which can't handle both + useprivilegeseparation=yes and compression=yes + - (djm) contrib/redhat/openssh.spec hacking: + - Merge in spec changes from seba@iq.pl (Sebastian Pachuta) + - Add new {ssh,sshd}_config.5 manpages + - Add new ssh-keysign program and remove setuid from ssh client + +20020620 + - (bal) Fixed AIX environment handling, use setpcred() instead of existing + code. (Bugzilla Bug 261) + - (bal) OpenBSD CVS Sync + - todd@cvs.openbsd.org 2002/06/14 21:35:00 + [monitor_wrap.c] + spelling; from Brian Poole + - markus@cvs.openbsd.org 2002/06/15 00:01:36 + [authfd.c authfd.h ssh-add.c ssh-agent.c] + break agent key lifetime protocol and allow other contraints for key + usage. + - markus@cvs.openbsd.org 2002/06/15 00:07:38 + [authfd.c authfd.h ssh-add.c ssh-agent.c] + fix stupid typo + - markus@cvs.openbsd.org 2002/06/15 01:27:48 + [authfd.c authfd.h ssh-add.c ssh-agent.c] + remove the CONSTRAIN_IDENTITY messages and introduce a new + ADD_ID message with contraints instead. contraints can be + only added together with the private key. + - itojun@cvs.openbsd.org 2002/06/16 21:30:58 + [ssh-keyscan.c] + use TAILQ_xx macro. from lukem@netbsd. markus ok + - deraadt@cvs.openbsd.org 2002/06/17 06:05:56 + [scp.c] + make usage like man page + - deraadt@cvs.openbsd.org 2002/06/19 00:27:55 + [auth-bsdauth.c auth-skey.c auth1.c auth2-chall.c auth2-none.c authfd.c + authfd.h monitor_wrap.c msg.c nchan.c radix.c readconf.c scp.c sftp.1 + ssh-add.1 ssh-add.c ssh-agent.1 ssh-agent.c ssh-keygen.1 ssh-keygen.c + ssh-keysign.c ssh.1 sshconnect.c sshconnect.h sshconnect2.c ttymodes.c + xmalloc.h] + KNF done automatically while reading.... + - markus@cvs.openbsd.org 2002/06/19 18:01:00 + [cipher.c monitor.c monitor_wrap.c packet.c packet.h] + make the monitor sync the transfer ssh1 session key; + transfer keycontext only for RC4 (this is still depends on EVP + implementation details and is broken). + - stevesk@cvs.openbsd.org 2002/06/20 19:56:07 + [ssh.1 sshd.8] + move configuration file options from ssh.1/sshd.8 to + ssh_config.5/sshd_config.5; ok deraadt@ millert@ + - stevesk@cvs.openbsd.org 2002/06/20 20:00:05 + [scp.1 sftp.1] + ssh_config(5) + - stevesk@cvs.openbsd.org 2002/06/20 20:03:34 + [ssh_config sshd_config] + refer to config file man page + - markus@cvs.openbsd.org 2002/06/20 23:05:56 + [servconf.c servconf.h session.c sshd.c] + allow Compression=yes/no in sshd_config + - markus@cvs.openbsd.org 2002/06/20 23:37:12 + [sshd_config] + add Compression + - stevesk@cvs.openbsd.org 2002/05/25 20:40:08 + [LICENCE] + missed Per Allansson (auth2-chall.c) + - (bal) Cygwin special handling of empty passwords wrong. Patch by + vinschen@redhat.com + - (bal) Missed integrating ssh_config.5 and sshd_config.5 + - (bal) Still more Makefile.in updates for ssh{d}_config.5 + +20020613 + - (bal) typo of setgroup for cygwin. Patch by vinschen@redhat.com + +20020612 + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/06/11 23:03:54 + [ssh.c] + remove unused cruft. + - markus@cvs.openbsd.org 2002/06/12 01:09:52 + [ssh.c] + ssh_connect returns 0 on success + - (bal) Build noop setgroups() for cygwin to clean up code (For other + platforms without the setgroups() requirement, you MUST define + SETGROUPS_NOOP in the configure.ac) Based on patch by vinschen@redhat.com + - (bal) Some platforms don't have ONLCR (Notable Mint) + +20020611 + - (bal) ssh-agent.c RCSD fix (|unexpand already done) + - (bal) OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2002/06/09 22:15:15 + [ssh.1] + update for no setuid root and ssh-keysign; ok deraadt@ + - itojun@cvs.openbsd.org 2002/06/09 22:17:21 + [sshconnect.c] + pass salen to sockaddr_ntop so that we are happy on linux/solaris + - stevesk@cvs.openbsd.org 2002/06/10 16:53:06 + [auth-rsa.c ssh-rsa.c] + display minimum RSA modulus in error(); ok markus@ + - stevesk@cvs.openbsd.org 2002/06/10 16:56:30 + [ssh-keysign.8] + merge in stuff from my man page; ok markus@ + - stevesk@cvs.openbsd.org 2002/06/10 17:36:23 + [ssh-add.1 ssh-add.c] + use convtime() to parse and validate key lifetime. can now + use '-t 2h' etc. ok markus@ provos@ + - stevesk@cvs.openbsd.org 2002/06/10 17:45:20 + [readconf.c ssh.1] + change RhostsRSAAuthentication and RhostsAuthentication default to no + since ssh is no longer setuid root by default; ok markus@ + - stevesk@cvs.openbsd.org 2002/06/10 21:21:10 + [ssh_config] + update defaults for RhostsRSAAuthentication and RhostsAuthentication + here too (all options commented out with default value). + - markus@cvs.openbsd.org 2002/06/10 22:28:41 + [channels.c channels.h session.c] + move creation of agent socket to session.c; no need for uidswapping + in channel.c. + - markus@cvs.openbsd.org 2002/06/11 04:14:26 + [ssh.c sshconnect.c sshconnect.h] + no longer use uidswap.[ch] from the ssh client + run less code with euid==0 if ssh is installed setuid root + just switch the euid, don't switch the complete set of groups + (this is only needed by sshd). ok provos@ + - mpech@cvs.openbsd.org 2002/06/11 05:46:20 + [auth-krb4.c monitor.h serverloop.c session.c ssh-agent.c sshd.c] + pid_t cleanup. Markus need this now to keep hacking. + markus@, millert@ ok + - itojun@cvs.openbsd.org 2002/06/11 08:11:45 + [canohost.c] + use "ntop" only after initialized + - (bal) Cygwin fix up from swap uid clean up in ssh.c patch by + vinschen@redhat.com + +20020609 + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/06/08 05:07:56 + [ssh.c] + nuke ptrace comment + - markus@cvs.openbsd.org 2002/06/08 05:07:09 + [ssh-keysign.c] + only accept 20 byte session ids + - markus@cvs.openbsd.org 2002/06/08 05:17:01 + [readconf.c readconf.h ssh.1 ssh.c] + deprecate FallBackToRsh and UseRsh; patch from djm@ + - markus@cvs.openbsd.org 2002/06/08 05:40:01 + [readconf.c] + just warn about Deprecated options for now + - markus@cvs.openbsd.org 2002/06/08 05:41:18 + [ssh_config] + remove FallBackToRsh/UseRsh + - markus@cvs.openbsd.org 2002/06/08 12:36:53 + [scp.c] + remove FallBackToRsh + - markus@cvs.openbsd.org 2002/06/08 12:46:14 + [readconf.c] + silently ignore deprecated options, since FallBackToRsh might be passed + by remote scp commands. + - itojun@cvs.openbsd.org 2002/06/08 21:15:27 + [sshconnect.c] + always use getnameinfo. (diag message only) + - markus@cvs.openbsd.org 2002/06/09 04:33:27 + [sshconnect.c] + abort() - > fatal() + - (bal) RCSID tag updates on channels.c, clientloop.c, nchan.c, + sftp-client.c, ssh-agenet.c, ssh-keygen.c and connect.h (we did unexpand + independant of them) + +20020607 + - (bal) Removed --{enable/disable}-suid-ssh + - (bal) Missed __progname in ssh-keysign.c patch by dtucker@zip.com.au + - (bal) use 'LOGIN_PROGRAM' not '/usr/bin/login' in session.c patch by + Bertrand.Velle@apogee-com.fr + +20020606 + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/05/15 21:56:38 + [servconf.c sshd.8 sshd_config] + re-enable privsep and disable setuid for post-3.2.2 + - markus@cvs.openbsd.org 2002/05/16 22:02:50 + [cipher.c kex.h mac.c] + fix warnings (openssl 0.9.7 requires const) + - stevesk@cvs.openbsd.org 2002/05/16 22:09:59 + [session.c ssh.c] + don't limit xauth pathlen on client side and longer print length on + server when debug; ok markus@ + - deraadt@cvs.openbsd.org 2002/05/19 20:54:52 + [log.h] + extra commas in enum not 100% portable + - deraadt@cvs.openbsd.org 2002/05/22 23:18:25 + [ssh.c sshd.c] + spelling; abishoff@arc.nasa.gov + - markus@cvs.openbsd.org 2002/05/23 19:24:30 + [authfile.c authfile.h pathnames.h ssh.c sshconnect.c sshconnect.h + sshconnect1.c sshconnect2.c ssh-keysign.8 ssh-keysign.c Makefile.in] + add /usr/libexec/ssh-keysign: a setuid helper program for hostbased + authentication in protocol v2 (needs to access the hostkeys). + - markus@cvs.openbsd.org 2002/05/23 19:39:34 + [ssh.c] + add comment about ssh-keysign + - markus@cvs.openbsd.org 2002/05/24 08:45:14 + [sshconnect2.c] + stat ssh-keysign first, print error if stat fails; + some debug->error; fix comment + - markus@cvs.openbsd.org 2002/05/25 08:50:39 + [sshconnect2.c] + execlp->execl; from stevesk + - markus@cvs.openbsd.org 2002/05/25 18:51:07 + [auth.h auth2.c auth2-hostbased.c auth2-kbdint.c auth2-none.c + auth2-passwd.c auth2-pubkey.c Makefile.in] + split auth2.c into one file per method; ok provos@/deraadt@ + - stevesk@cvs.openbsd.org 2002/05/26 20:35:10 + [ssh.1] + sort ChallengeResponseAuthentication; ok markus@ + - stevesk@cvs.openbsd.org 2002/05/28 16:45:27 + [monitor_mm.c] + print strerror(errno) on mmap/munmap error; ok markus@ + - stevesk@cvs.openbsd.org 2002/05/28 17:28:02 + [uidswap.c] + format spec change/casts and some KNF; ok markus@ + - stevesk@cvs.openbsd.org 2002/05/28 21:24:00 + [uidswap.c] + use correct function name in fatal() + - stevesk@cvs.openbsd.org 2002/05/29 03:06:30 + [ssh.1 sshd.8] + spelling + - markus@cvs.openbsd.org 2002/05/29 11:21:57 + [sshd.c] + don't start if privsep is enabled and SSH_PRIVSEP_USER or + _PATH_PRIVSEP_CHROOT_DIR are missing; ok deraadt@ + - markus@cvs.openbsd.org 2002/05/30 08:07:31 + [cipher.c] + use rijndael/aes from libcrypto (openssl >= 0.9.7) instead of + our own implementation. allow use of AES hardware via libcrypto, + ok deraadt@ + - markus@cvs.openbsd.org 2002/05/31 10:30:33 + [sshconnect2.c] + extent ssh-keysign protocol: + pass # of socket-fd to ssh-keysign, keysign verfies locally used + ip-address using this socket-fd, restricts fake local hostnames + to actual local hostnames; ok stevesk@ + - markus@cvs.openbsd.org 2002/05/31 11:35:15 + [auth.h auth2.c] + move Authmethod definitons to per-method file. + - markus@cvs.openbsd.org 2002/05/31 13:16:48 + [key.c] + add comment: + key_verify returns 1 for a correct signature, 0 for an incorrect signature + and -1 on error. + - markus@cvs.openbsd.org 2002/05/31 13:20:50 + [ssh-rsa.c] + pad received signature with leading zeros, because RSA_verify expects + a signature of RSA_size. the drafts says the signature is transmitted + unpadded (e.g. putty does not pad), reported by anakin@pobox.com + - deraadt@cvs.openbsd.org 2002/06/03 12:04:07 + [ssh.h] + compatiblity -> compatibility + decriptor -> descriptor + authentciated -> authenticated + transmition -> transmission + - markus@cvs.openbsd.org 2002/06/04 19:42:35 + [monitor.c] + only allow enabled authentication methods; ok provos@ + - markus@cvs.openbsd.org 2002/06/04 19:53:40 + [monitor.c] + save the session id (hash) for ssh2 (it will be passed with the + initial sign request) and verify that this value is used during + authentication; ok provos@ + - markus@cvs.openbsd.org 2002/06/04 23:02:06 + [packet.c] + remove __FUNCTION__ + - markus@cvs.openbsd.org 2002/06/04 23:05:49 + [cipher.c monitor.c monitor_fdpass.c monitor_mm.c monitor_wrap.c] + __FUNCTION__ -> __func__ + - markus@cvs.openbsd.org 2002/06/05 16:08:07 + [ssh-agent.1 ssh-agent.c] + '-a bind_address' binds the agent to user-specified unix-domain + socket instead of /tmp/ssh-XXXXXXXX/agent.; ok djm@ (some time ago). + - markus@cvs.openbsd.org 2002/06/05 16:08:07 + [ssh-agent.1 ssh-agent.c] + '-a bind_address' binds the agent to user-specified unix-domain + socket instead of /tmp/ssh-XXXXXXXX/agent.; ok djm@ (some time ago). + - markus@cvs.openbsd.org 2002/06/05 16:48:54 + [ssh-agent.c] + copy current request into an extra buffer and just flush this + request on errors, ok provos@ + - markus@cvs.openbsd.org 2002/06/05 19:57:12 + [authfd.c authfd.h ssh-add.1 ssh-add.c ssh-agent.c] + ssh-add -x for lock and -X for unlocking the agent. + todo: encrypt private keys with locked... + - markus@cvs.openbsd.org 2002/06/05 20:56:39 + [ssh-add.c] + add -x/-X to usage + - markus@cvs.openbsd.org 2002/06/05 21:55:44 + [authfd.c authfd.h ssh-add.1 ssh-add.c ssh-agent.c] + ssh-add -t life, Set lifetime (in seconds) when adding identities; + ok provos@ + - stevesk@cvs.openbsd.org 2002/06/06 01:09:41 + [monitor.h] + no trailing comma in enum; china@thewrittenword.com + - markus@cvs.openbsd.org 2002/06/06 17:12:44 + [sftp-server.c] + discard remaining bytes of current request; ok provos@ + - markus@cvs.openbsd.org 2002/06/06 17:30:11 + [sftp-server.c] + use get_int() macro (hide iqueue) + - (bal) Missed msg.[ch] in merge. Required for ssh-keysign. + - (bal) Forgot to add msg.c Makefile.in. + - (bal) monitor_mm.c typos. + - (bal) Refixed auth2.c. It was never fully commited while spliting out + authentication to different files. + - (bal) ssh-keysign should build and install correctly now. Phase two + would be to clean out any dead wood and disable ssh setuid on install. + - (bal) Reverse logic, use __func__ first since it's C99 + +20020604 + - (stevesk) [channels.c] bug #164 patch from YOSHIFUJI Hideaki (changed + setsockopt from debug to error for now). + +20020527 + - (tim) [configure.ac.orig monitor_fdpass.c] Enahnce msghdr tests to address + build problem on Irix reported by Dave Love . Back out + last monitor_fdpass.c changes that are no longer needed with new tests. + Patch tested on Irix by Jan-Frode Myklebust + +20020522 + - (djm) Fix spelling mistakes, spotted by Solar Designer i + + - Sync scard/ (not sure when it drifted) + - (djm) OpenBSD CVS Sync: + [auth.c] + Fix typo/thinko. Pass in as to auth_approval(), not NULL. + Closes PR 2659. + - Crank version + - Crank RPM spec versions + +20020521 + - (stevesk) [sshd.c] bug 245; disable setsid() for now + - (stevesk) [sshd.c] #ifndef HAVE_CYGWIN for setgroups() + +20020517 + - (tim) [configure.ac] remove extra MD5_MSG="no" line. + +20020515 + - (bal) CVS ID fix up on auth-passwd.c + - (bal) OpenBSD CVS Sync + - deraadt@cvs.openbsd.org 2002/05/07 19:54:36 + [ssh.h] + use ssh uid + - deraadt@cvs.openbsd.org 2002/05/08 21:06:34 + [ssh.h] + move to sshd.sshd instead + - stevesk@cvs.openbsd.org 2002/05/11 20:24:48 + [ssh.h] + typo in comment + - itojun@cvs.openbsd.org 2002/05/13 02:37:39 + [auth-skey.c auth2.c] + less warnings. skey_{respond,query} are public (in auth.h) + - markus@cvs.openbsd.org 2002/05/13 20:44:58 + [auth-options.c auth.c auth.h] + move the packet_send_debug handling from auth-options.c to auth.c; + ok provos@ + - millert@cvs.openbsd.org 2002/05/13 15:53:19 + [sshd.c] + Call setsid() in the child after sshd accepts the connection and forks. + This is needed for privsep which calls setlogin() when it changes uids. + Without this, there is a race where the login name of an existing + connection, as returned by getlogin(), may be changed to the privsep + user (sshd). markus@ OK + - markus@cvs.openbsd.org 2002/05/13 21:26:49 + [auth-rhosts.c] + handle debug messages during rhosts-rsa and hostbased authentication; + ok provos@ + - mouring@cvs.openbsd.org 2002/05/15 15:47:49 + [kex.c monitor.c monitor_wrap.c sshd.c] + 'monitor' variable clashes with at least one lame platform (NeXT). i + Renamed to 'pmonitor'. provos@ + - deraadt@cvs.openbsd.org 2002/05/04 02:39:35 + [servconf.c sshd.8 sshd_config] + enable privsep by default; provos ok + - millert@cvs.openbsd.org 2002/05/06 23:34:33 + [ssh.1 sshd.8] + Kill/adjust r(login|exec)d? references now that those are no longer in + the tree. + - markus@cvs.openbsd.org 2002/05/15 21:02:53 + [servconf.c sshd.8 sshd_config] + disable privsep and enable setuid for the 3.2.2 release + - (bal) Fixed up PAM case. I think. + - (bal) Clarified openbsd-compat/*-cray.* Licence provided by Wendy + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/05/15 21:05:29 + [version.h] + enter OpenSSH_3.2.2 + - (bal) Caldara, Suse, and Redhat openssh.specs updated. + +20020514 + - (stevesk) [README.privsep] PAM+privsep works with Solaris 8. + - (tim) [sshpty.c] set tty modes when allocating old style bsd ptys to + match what newer style ptys have when allocated. Based on a patch by + Roger Cornelius + - (tim) [README.privsep] UnixWare 7 and OpenUNIX 8 work. + - (tim) [README.privsep] remove reference to UnixWare 7 and OpenUNIX 8 + from PAM-enabled pragraph. UnixWare has no PAM. + - (tim) [contrib/caldera/openssh.spec] update version. + +20020513 + - (stevesk) add initial README.privsep + - (stevesk) [configure.ac] nicer message: --with-privsep-user=user + - (djm) Add --with-superuser-path=xxx configure option to specify + what $PATH the superuser receives. + - (djm) Bug #231: UsePrivilegeSeparation turns off Banner. + - (djm) Add --with-privsep-path configure option + - (djm) Update RPM spec file: different superuser path, use + /var/empty/sshd for privsep + - (djm) Bug #234: missing readpassphrase declaration and defines + - (djm) Add INSTALL warning about SSH protocol 1 blowfish w/ + OpenSSL < 0.9.6 + +20020511 + - (tim) [configure.ac] applied a rework of djm's OpenSSL search cleanup patch. + Now only searches system and /usr/local/ssl (OpenSSL's default install path) + Others must use --with-ssl-dir=.... + - (tim) [monitor_fdpass.c] fix for systems that have both + HAVE_ACCRIGHTS_IN_MSGHDR and HAVE_CONTROL_IN_MSGHDR. Ie. sys/socket.h + has #define msg_accrights msg_control + +20020510 + - (stevesk) [auth.c] Shadow account and expiration cleanup. Now + check for root forced expire. Still don't check for inactive. + - (djm) Rework RedHat RPM files. Based on spec from Nalin + Dahyabhai and patches from + Pekka Savola + - (djm) Try to drop supplemental groups at daemon startup. Patch from + RedHat + - (bal) Back all the way out of auth-passwd.c changes. Breaks too many + things that don't set pw->pw_passwd. + +20020509 + - (tim) [Makefile.in] Unbreak make -f Makefile.in distprep + +20020508 + - (tim) [openbsd-compat/bsd-arc4random.c] fix logic on when seed_rng() is + called. Report by Chris Maxwell + - (tim) [Makefile.in configure.ac] set SHELL variable in Makefile + - (djm) Disable PAM kbd-int auth if privsep is turned on (it doesn't work) + +20020507 + - (tim) [configure.ac openbsd-compat/bsd-misc.c openbsd-compat/bsd-misc.h] + Add truncate() emulation to address Bug 208 + +20020506 + - (djm) Unbreak auth-passwd.c for PAM and SIA + - (djm) Unbreak PAM auth for protocol 1. Report from Pekka Savola + + - (djm) Don't reinitialise PAM credentials before we have started PAM. + Report from Pekka Savola + +20020506 + - (bal) Fixed auth-passwd.c to resolve PermitEmptyPassword issue + +20020501 + - (djm) Import OpenBSD regression tests. Requires BSD make to run + - (djm) Fix readpassphase compilation for systems which have it + +20020429 + - (tim) [contrib/caldera/openssh.spec] update fixUP to reflect changes in + sshd_config. + - (tim) [contrib/cygwin/README] remove reference to regex. + patch from Corinna Vinschen + +20020426 + - (djm) Bug #137, #209: fix make problems for scard/Ssh.bin, do uudecode + during distprep only + - (djm) Disable PAM password expiry until a complete fix for bug #188 + exists + - (djm) Bug #180: Set ToS bits on IPv4-in-IPv6 mapped addresses. Based on + patch from openssh@misc.tecq.org + +20020425 + - (stevesk) [defines.h] remove USE_TIMEVAL; unused + - (stevesk) [acconfig.h auth-passwd.c configure.ac sshd.c] HP-UX 10.26 + support. bug #184. most from dcole@keysoftsys.com. + +20020424 + - (djm) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/04/23 12:54:10 + [version.h] + 3.2.1 + - djm@cvs.openbsd.org 2002/04/23 22:16:29 + [sshd.c] + Improve error message; ok markus@ stevesk@ + +20020423 + - (stevesk) [acconfig.h configure.ac session.c] LOGIN_NO_ENDOPT for HP-UX + - (stevesk) [acconfig.h] NEED_IN_SYSTM_H unused + - (markus) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/04/23 12:58:26 + [radix.c] + send complete ticket; semerad@ss1000.ms.mff.cuni.cz + - (djm) Trim ChangeLog to include only post-3.1 changes + - (djm) Update RPM spec file versions + - (djm) Redhat spec enables KrbV by default + - (djm) Applied OpenSC smartcard updates from Markus & + Antti Tapaninen + - (djm) Define BROKEN_REALPATH for AIX, patch from + Antti Tapaninen + - (djm) Bug #214: Fix utmp for Irix (don't strip "tty"). Patch from + Kevin Taylor (??) via Philipp Grau + + - (djm) Bug #213: Simplify CMSG_ALIGN macros to avoid symbol clashes. + Reported by Doug Manton + - (djm) Bug #222: Fix tests for getaddrinfo on OSF/1. Spotted by + Robert Urban + - (djm) Bug #206 - blibpath isn't always needed for AIX ld, avoid + sizeof(long long int) == 4 breakage. Patch from Matthew Clarke + + - (djm) Make privsep work with PAM (still experimental) + - (djm) OpenBSD CVS Sync + - deraadt@cvs.openbsd.org 2002/04/20 09:02:03 + [servconf.c] + No, afs requires explicit enabling + - markus@cvs.openbsd.org 2002/04/20 09:14:58 + [bufaux.c bufaux.h] + add buffer_{get,put}_short + - markus@cvs.openbsd.org 2002/04/20 09:17:19 + [radix.c] + rewrite using the buffer_* API, fixes overflow; ok deraadt@ + - stevesk@cvs.openbsd.org 2002/04/21 16:19:27 + [sshd.8 sshd_config] + document default AFSTokenPassing no; ok deraadt@ + - stevesk@cvs.openbsd.org 2002/04/21 16:25:06 + [sshconnect1.c] + spelling in error message; ok markus@ + - markus@cvs.openbsd.org 2002/04/22 06:15:47 + [radix.c] + fix check for overflow + - markus@cvs.openbsd.org 2002/04/22 16:16:53 + [servconf.c sshd.8 sshd_config] + do not auto-enable KerberosAuthentication; ok djm@, provos@, deraadt@ + - markus@cvs.openbsd.org 2002/04/22 21:04:52 + [channels.c clientloop.c clientloop.h ssh.c] + request reply (success/failure) for -R style fwd in protocol v2, + depends on ordered replies. + fixes http://bugzilla.mindrot.org/show_bug.cgi?id=215; ok provos@ + +20020421 + - (tim) [entropy.c.] Portability fix for SCO Unix 3.2v4.x (SCO OSR 3.0). + entropy.c needs seteuid(getuid()) for the setuid(original_uid) to + succeed. Patch by gert@greenie.muc.de. This fixes one part of Bug 208 + +20020418 + - (djm) Avoid SIGCHLD breakage when run from rsync. Fix from + Sturle Sunde + +20020417 + - (djm) Tell users to configure /dev/random support into OpenSSL in + INSTALL + - (djm) Fix .Nm in mdoc2man.pl from pspencer@fields.utoronto.ca + - (tim) [configure.ac] Issue warning on --with-default-path=/some_path + if LOGIN_CAP is enabled. Report & testing by Tuc + +20020415 + - (djm) Unbreak "make install". Fix from Darren Tucker + + - (stevesk) bsd-cygwin_util.[ch] BSD license from Corinna Vinschen + - (tim) [configure.ac] add tests for recvmsg and sendmsg. + [monitor_fdpass.c] add checks for HAVE_SENDMSG and HAVE_RECVMSG for + systems that HAVE_ACCRIGHTS_IN_MSGHDR but no recvmsg or sendmsg. + +20020414 + - (djm) ssh-rand-helper improvements + - Add commandline debugging options + - Don't write binary data if stdout is a tty (use hex instead) + - Give it a manpage + - (djm) Random number collection doc fixes from Ben + +20020413 + - (djm) Add KrbV support patch from Simon Wilkinson + +20020412 + - (stevesk) [auth-sia.[ch]] add BSD license from Chris Adams + - (tim) [configure.ac] add to msghdr tests. Change -L + to -h on testing for /bin being symbolic link + - (bal) Mistaken in Cygwin scripts for ssh starting. Patch by + Corinna Vinschen + - (bal) disable privsep if no MAP_ANON. We can re-enable it + after the release when we can do more testing. + +20020411 + - (stevesk) [auth-sia.c] cleanup + - (tim) [acconfig.h defines.h includes.h] put includes in includes.h and + defines in defines.h [rijndael.c openbsd-compat/fake-socket.h + openbsd-compat/inet_aton.c] include "includes.h" instead of "config.h" + ok stevesk@ + +20020410 + - (stevesk) [configure.ac monitor.c] HAVE_SOCKETPAIR + - (stevesk) [auth-sia.c] compile fix Chris Adams + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/04/10 08:21:47 + [auth1.c compat.c compat.h] + strip '@' from username only for KerbV and known broken clients, + bug #204 + - markus@cvs.openbsd.org 2002/04/10 08:56:01 + [version.h] + OpenSSH_3.2 + - Added p1 to idenify Portable release version. + +20020408 + - (bal) Minor OpenSC updates. Fix up header locations and update + README.smartcard provided by Juha Yrjölä + +20020407 + - (stevesk) HAVE_CONTROL_IN_MSGHDR; not used right now. + Future: we may want to test if fd passing works correctly. + - (stevesk) [monitor_fdpass.c] fatal() for UsePrivilegeSeparation=yes + and no fd passing support. + - (stevesk) HAVE_MMAP and HAVE_SYS_MMAN_H and use them in + monitor_mm.c + - (stevesk) remove configure support for poll.h; it was removed + from sshd.c a long time ago. + - (stevesk) --with-privsep-user; default sshd + - (stevesk) wrap munmap() with HAVE_MMAP also. + +20020406 + - (djm) Typo in Suse SPEC file. Fix from Carsten Grohmann + + - (bal) Added MAP_FAILED to allow AIX and Trusted HP to compile. + - (bal) OpenBSD CVS Sync + - djm@cvs.openbsd.org 2002/04/06 00:30:08 + [sftp-client.c] + Fix occasional corruption on upload due to bad reuse of request + id, spotted by chombier@mac.com; ok markus@ + - mouring@cvs.openbsd.org 2002/04/06 18:24:09 + [scp.c] + Fixes potental double // within path. + http://bugzilla.mindrot.org/show_bug.cgi?id=76 + - (bal) Slight update to OpenSC support. Better version checking. patch + by Juha Yrjölä + - (bal) Revered out of runtime IRIX detection of joblimits. Code is + incomplete. + - (bal) Quiet down configure.ac if /bin/test does not exist. + - (bal) We no longer use atexit()/xatexit()/on_exit() + +20020405 + - (bal) Patch for OpenSC SmartCard library; ok markus@; patch by + Juha Yrjölä + - (bal) Minor documentation update to reflect smartcard library + support changes. + - (bal) Too many issues. Remove all workarounds and + using internal version only. + - (bal) OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2002/04/05 20:56:21 + [sshd.8] + clarify sshrc some and handle X11UseLocalhost=yes; ok markus@ + +20020404 + - (stevesk) [auth-pam.c auth-pam.h auth-passwd.c auth-sia.c auth-sia.h + auth1.c auth2.c] PAM, OSF_SIA password auth cleanup; from djm. + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/04/03 09:26:11 + [cipher.c myproposal.h] + re-add rijndael-cbc@lysator.liu.se for MacSSH; ash@lab.poc.net + +20020402 + - (bal) Hand Sync of scp.c (reverted to upstream code) + - deraadt@cvs.openbsd.org 2002/03/30 17:45:46 + [scp.c] + stretch banners + - (bal) CVS ID sync of uidswap.c + - (bal) OpenBSD CVS Sync (now for the real sync) + - markus@cvs.openbsd.org 2002/03/27 22:21:45 + [ssh-keygen.c] + try to import keys with extra trailing === (seen with ssh.com < + 2.0.12) + - markus@cvs.openbsd.org 2002/03/28 15:34:51 + [session.c] + do not call record_login twice (for use_privsep) + - markus@cvs.openbsd.org 2002/03/29 18:59:32 + [session.c session.h] + retrieve last login time before the pty is allocated, store per + session + - stevesk@cvs.openbsd.org 2002/03/29 19:16:22 + [sshd.8] + RSA key modulus size minimum 768; ok markus@ + - stevesk@cvs.openbsd.org 2002/03/29 19:18:33 + [auth-rsa.c ssh-rsa.c ssh.h] + make RSA modulus minimum #define; ok markus@ + - markus@cvs.openbsd.org 2002/03/30 18:51:15 + [monitor.c serverloop.c sftp-int.c sftp.c sshd.c] + check waitpid for EINTR; based on patch from peter@ifm.liu.se + - markus@cvs.openbsd.org 2002/04/01 22:02:16 + [sftp-client.c] + 20480 is an upper limit for older server + - markus@cvs.openbsd.org 2002/04/01 22:07:17 + [sftp-client.c] + fallback to stat if server does not support lstat + - markus@cvs.openbsd.org 2002/04/02 11:49:39 + [ssh-agent.c] + check $SHELL for -k and -d, too; + http://bugzilla.mindrot.org/show_bug.cgi?id=199 + - markus@cvs.openbsd.org 2002/04/02 17:37:48 + [sftp.c] + always call log_init() + - markus@cvs.openbsd.org 2002/04/02 20:11:38 + [ssh-rsa.c] + ignore SSH_BUG_SIGBLOB for ssh-rsa; #187 + - (bal) mispelling in uidswap.c (portable only) + +20020401 + - (stevesk) [monitor.c] PAM should work again; will *not* work with + UsePrivilegeSeparation=yes. + - (stevesk) [auth1.c] fix password auth for protocol 1 when + !USE_PAM && !HAVE_OSF_SIA; merge issue. + +20020331 + - (tim) [configure.ac] use /bin/test -L to work around broken builtin on + Solaris 8 + - (tim) [sshconnect2.c] change uint32_t to u_int32_t + +20020330 + - (stevesk) [configure.ac] remove header check for sys/ttcompat.h + bug 167 + +20020327 + - (bal) 'pw' should be 'authctxt->pw' in auth1.c spotted by + kent@lysator.liu.se + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/03/26 11:34:49 + [ssh.1 sshd.8] + update to recent drafts + - markus@cvs.openbsd.org 2002/03/26 11:37:05 + [ssh.c] + update Copyright + - markus@cvs.openbsd.org 2002/03/26 15:23:40 + [bufaux.c] + do not talk about packets in bufaux + - rees@cvs.openbsd.org 2002/03/26 18:46:59 + [scard.c] + try_AUT0 in read_pubkey too, for those paranoid few who want to + acl 'sh' + - markus@cvs.openbsd.org 2002/03/26 22:50:39 + [channels.h] + CHANNEL_EFD_OUTPUT_ACTIVE is false for CHAN_CLOSE_RCVD, too + - markus@cvs.openbsd.org 2002/03/26 23:13:03 + [auth-rsa.c] + disallow RSA keys < 768 for protocol 1, too (rhosts-rsa and rsa auth) + - markus@cvs.openbsd.org 2002/03/26 23:14:51 + [kex.c] + generate a new cookie for each SSH2_MSG_KEXINIT message we send out + - mouring@cvs.openbsd.org 2002/03/27 11:45:42 + [monitor.c] + monitor_allowed_key() returns int instead of pointer. ok markus@ + +20020325 + - (stevesk) import OpenBSD as "openbsd-compat/tree.h" + - (bal) OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2002/03/23 20:57:26 + [sshd.c] + setproctitle() after preauth child; ok markus@ + - markus@cvs.openbsd.org 2002/03/24 16:00:27 + [serverloop.c] + remove unused debug + - markus@cvs.openbsd.org 2002/03/24 16:01:13 + [packet.c] + debug->debug3 for extra padding + - stevesk@cvs.openbsd.org 2002/03/24 17:27:03 + [kexgex.c] + typo; ok markus@ + - stevesk@cvs.openbsd.org 2002/03/24 17:53:16 + [monitor_fdpass.c] + minor cleanup and more error checking; ok markus@ + - markus@cvs.openbsd.org 2002/03/24 18:05:29 + [scard.c] + we need to figure out AUT0 for sc_private_encrypt, too + - stevesk@cvs.openbsd.org 2002/03/24 23:20:00 + [monitor.c] + remove "\n" from fatal() + - markus@cvs.openbsd.org 2002/03/25 09:21:13 + [auth-rsa.c] + return 0 (not NULL); tomh@po.crl.go.jp + - markus@cvs.openbsd.org 2002/03/25 09:25:06 + [auth-rh-rsa.c] + rm bogus comment + - markus@cvs.openbsd.org 2002/03/25 17:34:27 + [scard.c scard.h ssh-agent.c ssh-keygen.c ssh.c] + change sc_get_key to sc_get_keys and hide smartcard details in scard.c + - stevesk@cvs.openbsd.org 2002/03/25 20:12:10 + [monitor_mm.c monitor_wrap.c] + ssize_t args use "%ld" and cast to (long) + size_t args use "%lu" and cast to (u_long) + ok markus@ and thanks millert@ + - markus@cvs.openbsd.org 2002/03/25 21:04:02 + [ssh.c] + simplify num_identity_files handling + - markus@cvs.openbsd.org 2002/03/25 21:13:51 + [channels.c channels.h compat.c compat.h nchan.c] + don't send stderr data after EOF, accept this from older known + (broken) sshd servers only, fixes + http://bugzilla.mindrot.org/show_bug.cgi?id=179 + - stevesk@cvs.openbsd.org 2002/03/26 03:24:01 + [monitor.h monitor_fdpass.h monitor_mm.h monitor_wrap.h] + $OpenBSD$ + +20020324 + - (stevesk) [session.c] disable LOGIN_NEEDS_TERM until we are sure + it can be removed. only used on solaris. will no longer compile with + privsep shuffling. + +20020322 + - (stevesk) HAVE_ACCRIGHTS_IN_MSGHDR configure support + - (stevesk) [monitor.c monitor_wrap.c] #ifdef HAVE_PW_CLASS_IN_PASSWD + - (stevesk) configure and cpp __FUNCTION__ gymnastics to handle nielsisms + - (stevesk) [monitor_fdpass.c] support for access rights style file + descriptor passing + - (stevesk) [auth2.c] merge cleanup/sync + - (stevesk) [defines.h] hp-ux 11 has ancillary data style fd passing, but + is missing CMSG_LEN() and CMSG_SPACE() macros. + - (stevesk) [defines.h] #define MAP_ANON MAP_ANONYMOUS for HP-UX; other + platforms may need this--I'm not sure. mmap() issues will need to be + addressed further. + - (tim) [cipher.c] fix problem with OpenBSD sync + - (stevesk) [LICENCE] OpenBSD sync + +20020321 + - (bal) OpenBSD CVS Sync + - itojun@cvs.openbsd.org 2002/03/08 06:10:16 + [sftp-client.c] + printf type mismatch + - itojun@cvs.openbsd.org 2002/03/11 03:18:49 + [sftp-client.c] + correct type mismatches (u_int64_t != unsigned long long) + - itojun@cvs.openbsd.org 2002/03/11 03:19:53 + [sftp-client.c] + indent + - markus@cvs.openbsd.org 2002/03/14 15:24:27 + [sshconnect1.c] + don't trust size sent by (rogue) server; noted by + s.esser@e-matters.de + - markus@cvs.openbsd.org 2002/03/14 16:38:26 + [sshd.c] + split out ssh1 session key decryption; ok provos@ + - markus@cvs.openbsd.org 2002/03/14 16:56:33 + [auth-rh-rsa.c auth-rsa.c auth.h] + split auth_rsa() for better readability and privsep; ok provos@ + - itojun@cvs.openbsd.org 2002/03/15 11:00:38 + [auth.c] + fix file type checking (use S_ISREG). ok by markus + - markus@cvs.openbsd.org 2002/03/16 11:24:53 + [compress.c] + skip inflateEnd if inflate fails; ok provos@ + - markus@cvs.openbsd.org 2002/03/16 17:22:09 + [auth-rh-rsa.c auth.h] + split auth_rhosts_rsa(), ok provos@ + - stevesk@cvs.openbsd.org 2002/03/16 17:41:25 + [auth-krb5.c] + BSD license. from Daniel Kouril via Dug Song. ok markus@ + - provos@cvs.openbsd.org 2002/03/17 20:25:56 + [auth.c auth.h auth1.c auth2.c] + getpwnamallow returns struct passwd * only if user valid; + okay markus@ + - provos@cvs.openbsd.org 2002/03/18 01:12:14 + [auth.h auth1.c auth2.c sshd.c] + have the authentication functions return the authentication context + and then do_authenticated; okay millert@ + - dugsong@cvs.openbsd.org 2002/03/18 01:30:10 + [auth-krb4.c] + set client to NULL after xfree(), from Rolf Braun + + - provos@cvs.openbsd.org 2002/03/18 03:41:08 + [auth.c session.c] + move auth_approval into getpwnamallow with help from millert@ + - markus@cvs.openbsd.org 2002/03/18 17:13:15 + [cipher.c cipher.h] + export/import cipher states; needed by ssh-privsep + - markus@cvs.openbsd.org 2002/03/18 17:16:38 + [packet.c packet.h] + export/import cipher state, iv and ssh2 seqnr; needed by ssh-privsep + - markus@cvs.openbsd.org 2002/03/18 17:23:31 + [key.c key.h] + add key_demote() for ssh-privsep + - provos@cvs.openbsd.org 2002/03/18 17:25:29 + [bufaux.c bufaux.h] + buffer_skip_string and extra sanity checking; needed by ssh-privsep + - provos@cvs.openbsd.org 2002/03/18 17:31:54 + [compress.c] + export compression streams for ssh-privsep + - provos@cvs.openbsd.org 2002/03/18 17:50:31 + [auth-bsdauth.c auth-options.c auth-rh-rsa.c auth-rsa.c] + [auth-skey.c auth.h auth1.c auth2-chall.c auth2.c kex.c kex.h kexdh.c] + [kexgex.c servconf.c] + [session.h servconf.h serverloop.c session.c sshd.c] + integrate privilege separated openssh; its turned off by default + for now. work done by me and markus@ + - provos@cvs.openbsd.org 2002/03/18 17:53:08 + [sshd.8] + credits for privsep + - provos@cvs.openbsd.org 2002/03/18 17:59:09 + [sshd.8] + document UsePrivilegeSeparation + - stevesk@cvs.openbsd.org 2002/03/18 23:52:51 + [servconf.c] + UnprivUser/UnprivGroup usable now--specify numeric user/group; ok + provos@ + - stevesk@cvs.openbsd.org 2002/03/19 03:03:43 + [pathnames.h servconf.c servconf.h sshd.c] + _PATH_PRIVSEP_CHROOT_DIR; ok provos@ + - stevesk@cvs.openbsd.org 2002/03/19 05:23:08 + [sshd.8] + Banner has no default. + - mpech@cvs.openbsd.org 2002/03/19 06:32:56 + [sftp-int.c] + use xfree() after xstrdup(). + + markus@ ok + - markus@cvs.openbsd.org 2002/03/19 10:35:39 + [auth-options.c auth.h session.c session.h sshd.c] + clean up prototypes + - markus@cvs.openbsd.org 2002/03/19 10:49:35 + [auth-krb5.c auth-rh-rsa.c auth.c cipher.c key.c misc.h] + [packet.c session.c sftp-client.c sftp-glob.h sftp.c ssh-add.c ssh.c] + [sshconnect2.c sshd.c ttymodes.c] + KNF whitespace + - markus@cvs.openbsd.org 2002/03/19 14:27:39 + [auth.c auth1.c auth2.c] + make getpwnamallow() allways call pwcopy() + - markus@cvs.openbsd.org 2002/03/19 15:31:47 + [auth.c] + check for NULL; from provos@ + - stevesk@cvs.openbsd.org 2002/03/20 19:12:25 + [servconf.c servconf.h ssh.h sshd.c] + for unprivileged user, group do: + pw=getpwnam(SSH_PRIVSEP_USER); do_setusercontext(pw). ok provos@ + - stevesk@cvs.openbsd.org 2002/03/20 21:08:08 + [sshd.c] + strerror() on chdir() fail; ok provos@ + - markus@cvs.openbsd.org 2002/03/21 10:21:20 + [ssh-add.c] + ignore errors for nonexisting default keys in ssh-add, + fixes http://bugzilla.mindrot.org/show_bug.cgi?id=158 + - jakob@cvs.openbsd.org 2002/03/21 15:17:26 + [clientloop.c ssh.1] + add built-in command line for adding new port forwardings on the fly. + based on a patch from brian wellington. ok markus@. + - markus@cvs.openbsd.org 2002/03/21 16:38:06 + [scard.c] + make compile w/ openssl 0.9.7 + - markus@cvs.openbsd.org 2002/03/21 16:54:53 + [scard.c scard.h ssh-keygen.c] + move key upload to scard.[ch] + - markus@cvs.openbsd.org 2002/03/21 16:57:15 + [scard.c] + remove const + - markus@cvs.openbsd.org 2002/03/21 16:58:13 + [clientloop.c] + remove unused + - rees@cvs.openbsd.org 2002/03/21 18:08:15 + [scard.c] + In sc_put_key(), sc_reader_id should be id. + - markus@cvs.openbsd.org 2002/03/21 20:51:12 + [sshd_config] + add privsep (off) + - markus@cvs.openbsd.org 2002/03/21 21:23:34 + [sshd.c] + add privsep_preauth() and remove 1 goto; ok provos@ + - rees@cvs.openbsd.org 2002/03/21 21:54:34 + [scard.c scard.h ssh-keygen.c] + Add PIN-protection for secret key. + - rees@cvs.openbsd.org 2002/03/21 22:44:05 + [authfd.c authfd.h ssh-add.c ssh-agent.c ssh.c] + Add PIN-protection for secret key. + - markus@cvs.openbsd.org 2002/03/21 23:07:37 + [clientloop.c] + remove unused, sync w/ cmdline patch in my tree. + +20020317 + - (tim) [configure.ac] Assume path given with --with-pid-dir=PATH is + wanted, warn if directory does not exist. Put system directories in + front of PATH for finding entorpy commands. + - (tim) [contrib/aix/buildbff.sh contrib/aix/inventory.sh] AIX package + build fixes. Patch by Darren Tucker + [contrib/solaris/buildpkg.sh] add missing dirs to SYSTEM_DIR. Have + postinstall check for $piddir and add if necessary. + +20020311 + - (tim) [contrib/solaris/buildpkg.sh, contrib/solaris/README] Updated to + build on all platforms that support SVR4 style package tools. Now runs + from build dir. Parts are based on patches from Antonio Navarro, and + Darren Tucker. + +20020308 + - (djm) Revert bits of Markus' OpenSSL compat patch which was + accidentally committed. + - (djm) Add Markus' patch for compat wih OpenSSL < 0.9.6. + Known issue: Blowfish for SSH1 does not work + - (stevesk) entropy.c: typo in debug message + - (djm) ssh-keygen -i needs seeded RNG; report from markus@ + +$Id$ Index: src/crypto/openssh/FREEBSD-Xlist =================================================================== RCS file: src/crypto/openssh/FREEBSD-Xlist diff -N src/crypto/openssh/FREEBSD-Xlist --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/FREEBSD-Xlist 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,8 @@ +$FreeBSD: src/crypto/openssh/FREEBSD-Xlist,v 1.1 2002/06/29 10:39:02 des Exp $ +*.0 +*/.cvsignore +.cvsignore +autom4te* +config.h.in +configure +contrib Index: src/crypto/openssh/FREEBSD-upgrade =================================================================== RCS file: src/crypto/openssh/FREEBSD-upgrade diff -N src/crypto/openssh/FREEBSD-upgrade --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/FREEBSD-upgrade 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,130 @@ + + + FreeBSD maintainer's guide to OpenSSH-portable + ============================================== + + +0) Make sure your mail spool has plenty of free space. It'll fill up + pretty fast once you're done with this checklist. + +1) Grab the latest OpenSSH-portable tarball from the OpenBSD FTP + site (ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/) + +2) Unpack the tarball in a suitable directory. + +3) Remove trash: + + $ rm -rf $(cat FREEBSD-Xlist) + + Make sure that took care of everything, and if it didn't, make sure + to update FREEBSD-Xlist so you won't miss it the next time. + +4) Import the sources: + + $ cvs import src/crypto/openssh-portable OPENSSH OpenSSH_X_YpZ + +5) Resolve conflicts. Remember to bump the version number and + addendum in version.h. + +6) Generate configure and config.h.in: + + $ autoconf + $ autoheader + + Note: this requires a recent version of autoconf, not autoconf213. + +7) Run configure with the appropriate arguments: + + $ ./configure --prefix=/usr --sysconfdir=/etc/ssh \ + --with-pam --with-opie --with-tcp-wrappers + + Note that we don't want to configure OpenSSH for Kerberos using + configure since we have to be able to turn it on or off depending + on the value of MAKE_KERBEROS[45]. Our Makefiles take care of + this. + +8) Commit the resulting config.h. Make sure you don't accidentally + commit any other files created by autoconf, autoheader or + configure; they'll just clutter up the repo and cause trouble at + the next upgrade. + +9) Build and test. + +A) Re-commit everything on freefall (you *did* use a test repo for + this, didn't you?) + + + + An overview of FreeBSD changes to OpenSSH-portable + ================================================== + +0) VersionAddendum + + The SSH protocol allows for a human-readable version string of up + to 40 characters to be appended to the protocol version string. + FreeBSD takes advantage of this to include a date indicating the + "patch level", so people can easily determine whether their system + is vulnerable when an OpenSSH advisory goes out. Some people, + however, dislike advertising their patch level in the protocol + handshake, so we've added a VersionAddendum configuration variable + to allow them to change or disable it. + +1) Modified server-side defaults + + We've modified some configuration defaults in sshd: + + - For protocol version 2, we don't load RSA host keys by + default. If both RSA and DSA keys are present, we prefer DSA + to RSA. + + - LoginGraceTime defaults to 120 seconds instead of 600. + + - PermitRootLogin defaults to "no". + + - X11Forwarding defaults to "yes" (it's a threat to the client, + not to the server.) + + - Unless the config file says otherwise, we automatically enable + Kerberos support if an appropriate keytab is present. + + - PAMAuthenticationViaKbdInt defaults to "yes". + +2) Modified client-side defaults + + We've modified some configuration defaults in ssh: + + - For protocol version 2, if both RSA and DSA keys are present, + we prefer DSA to RSA. + + - CheckHostIP defaults to "no". + +3) Canonic host names + + We've added code to ssh.c to canonicize the target host name after + reading options but before trying to connect. This eliminates the + usual problem with duplicate known_hosts entries. + +4) OPIE + + We've added support for using OPIE as a drop-in replacement for + S/Key. + +5) PAM + + We use our own PAM code, which wraps PAM in a KbdintDevice and + works with privsep, instead of OpenSSH's own PAM code. + +6) setusercontext() environment + + Our setusercontext(3) can set environment variables, which we must + take care to transfer to the child's environment. + + + +This port was brought to you by (in no particular order) DARPA, NAI +Labs, ThinkSec, Nescafé, the Aberlour Glenlivet Distillery Co., +Suzanne Vega, and a Sanford's #69 Deluxe Marker. + + -- des@FreeBSD.org + +$FreeBSD: src/crypto/openssh/FREEBSD-upgrade,v 1.1 2002/06/29 10:39:14 des Exp $ Index: src/crypto/openssh/INSTALL =================================================================== RCS file: src/crypto/openssh/INSTALL diff -N src/crypto/openssh/INSTALL --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/INSTALL 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,224 @@ +1. Prerequisites +---------------- + +You will need working installations of Zlib and OpenSSL. + +Zlib: +http://www.gzip.org/zlib/ + +OpenSSL 0.9.6 or greater: +http://www.openssl.org/ + +(OpenSSL 0.9.5a is partially supported, but some ciphers (SSH protocol 1 +Blowfish included) do not work correctly.) + +RPMs of OpenSSL are available at http://violet.ibs.com.au/openssh/files/support. +For Red Hat Linux 6.2, they have been released as errata. RHL7 includes +these. + +OpenSSH can utilise Pluggable Authentication Modules (PAM) if your system +supports it. PAM is standard on Redhat and Debian Linux, Solaris and +HP-UX 11. + +NB. If you operating system supports /dev/random, you should configure +OpenSSL to use it. OpenSSH relies on OpenSSL's direct support of +/dev/random. If you don't you will have to rely on ssh-rand-helper, which +is inferior to a good kernel-based solution. + +PAM: +http://www.kernel.org/pub/linux/libs/pam/ + +If you wish to build the GNOME passphrase requester, you will need the GNOME +libraries and headers. + +GNOME: +http://www.gnome.org/ + +Alternatively, Jim Knoble has written an excellent X11 +passphrase requester. This is maintained separately at: + +http://www.ntrnet.net/~jmknoble/software/x11-ssh-askpass/index.html + +PRNGD: + +If your system lacks Kernel based random collection, the use of Lutz +Jaenicke's PRNGd is recommended. + +http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html + +EGD: + +The Entropy Gathering Daemon (EGD) is supported if you have a system which +lacks /dev/random and don't want to use OpenSSH's internal entropy collection. + +http://www.lothar.com/tech/crypto/ + +S/Key Libraries: +http://www.sparc.spb.su/solaris/skey/ + +If you wish to use --with-skey then you will need the above library +installed. No other current S/Key library is currently known to be +supported. + +2. Building / Installation +-------------------------- + +To install OpenSSH with default options: + +./configure +make +make install + +This will install the OpenSSH binaries in /usr/local/bin, configuration files +in /usr/local/etc, the server in /usr/local/sbin, etc. To specify a different +installation prefix, use the --prefix option to configure: + +./configure --prefix=/opt +make +make install + +Will install OpenSSH in /opt/{bin,etc,lib,sbin}. You can also override +specific paths, for example: + +./configure --prefix=/opt --sysconfdir=/etc/ssh +make +make install + +This will install the binaries in /opt/{bin,lib,sbin}, but will place the +configuration files in /etc/ssh. + +If you are using PAM, you may need to manually install a PAM control +file as "/etc/pam.d/sshd" (or wherever your system prefers to keep +them). Note that the service name used to start PAM is __progname, +which is the basename of the path of your sshd (e.g., the service name +for /usr/sbin/osshd will be osshd). If you have renamed your sshd +executable, your PAM configuration may need to be modified. + +A generic PAM configuration is included as "contrib/sshd.pam.generic", +you may need to edit it before using it on your system. If you are +using a recent version of Red Hat Linux, the config file in +contrib/redhat/sshd.pam should be more useful. Failure to install a +valid PAM file may result in an inability to use password +authentication. On HP-UX 11 and Solaris, the standard /etc/pam.conf +configuration will work with sshd (sshd will match the other service +name). + +There are a few other options to the configure script: + +--with-pam enables PAM support. + +--enable-gnome-askpass will build the GNOME passphrase dialog. You +need a working installation of GNOME, including the development +headers, for this to work. + +--with-prngd-socket=/some/file allows you to enable EGD or PRNGD +support and to specify a PRNGd socket. Use this if your Unix lacks +/dev/random and you don't want to use OpenSSH's builtin entropy +collection support. + +--with-prngd-port=portnum allows you to enable EGD or PRNGD support +and to specify a EGD localhost TCP port. Use this if your Unix lacks +/dev/random and you don't want to use OpenSSH's builtin entropy +collection support. + +--with-lastlog=FILE will specify the location of the lastlog file. +./configure searches a few locations for lastlog, but may not find +it if lastlog is installed in a different place. + +--without-lastlog will disable lastlog support entirely. + +--with-sia, --without-sia will enable or disable OSF1's Security +Integration Architecture. The default for OSF1 machines is enable. + +--with-kerberos4=PATH will enable Kerberos IV support. You will need +to have the Kerberos libraries and header files installed for this +to work. Use the optional PATH argument to specify the root of your +Kerberos installation. + +--with-afs=PATH will enable AFS support. You will need to have the +Kerberos IV and the AFS libraries and header files installed for this +to work. Use the optional PATH argument to specify the root of your +AFS installation. AFS requires Kerberos support to be enabled. + +--with-skey=PATH will enable S/Key one time password support. You will +need the S/Key libraries and header files installed for this to work. + +--with-tcp-wrappers will enable TCP Wrappers (/etc/hosts.allow|deny) +support. You will need libwrap.a and tcpd.h installed. + +--with-md5-passwords will enable the use of MD5 passwords. Enable this +if your operating system uses MD5 passwords without using PAM. + +--with-utmpx enables utmpx support. utmpx support is automatic for +some platforms. + +--without-shadow disables shadow password support. + +--with-ipaddr-display forces the use of a numeric IP address in the +$DISPLAY environment variable. Some broken systems need this. + +--with-default-path=PATH allows you to specify a default $PATH for sessions +started by sshd. This replaces the standard path entirely. + +--with-pid-dir=PATH specifies the directory in which the ssh.pid file is +created. + +--with-xauth=PATH specifies the location of the xauth binary + +--with-ipv4-default instructs OpenSSH to use IPv4 by default for new +connections. Normally OpenSSH will try attempt to lookup both IPv6 and +IPv4 addresses. On Linux/glibc-2.1.2 this causes long delays in name +resolution. If this option is specified, you can still attempt to +connect to IPv6 addresses using the command line option '-6'. + +--with-ssl-dir=DIR allows you to specify where your OpenSSL libraries +are installed. + +--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to +real (AF_INET) IPv4 addresses. Works around some quirks on Linux. + +--with-opensc=DIR +--with-sectok=DIR allows for OpenSC or sectok smartcard libraries to +be used with OpenSSH. See 'README.smartcard' for more details. + +If you need to pass special options to the compiler or linker, you +can specify these as environment variables before running ./configure. +For example: + +CFLAGS="-O -m486" LDFLAGS="-s" LIBS="-lrubbish" LD="/usr/foo/ld" ./configure + +3. Configuration +---------------- + +The runtime configuration files are installed by in ${prefix}/etc or +whatever you specified as your --sysconfdir (/usr/local/etc by default). + +The default configuration should be instantly usable, though you should +review it to ensure that it matches your security requirements. + +To generate a host key, run "make host-key". Alternately you can do so +manually using the following commands: + + ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N "" + ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" + ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N "" + +Replacing /etc/ssh with the correct path to the configuration directory. +(${prefix}/etc or whatever you specified with --sysconfdir during +configuration) + +If you have configured OpenSSH with EGD support, ensure that EGD is +running and has collected some Entropy. + +For more information on configuration, please refer to the manual pages +for sshd, ssh and ssh-agent. + +4. Problems? +------------ + +If you experience problems compiling, installing or running OpenSSH. +Please refer to the "reporting bugs" section of the webpage at +http://www.openssh.com/ + + +$Id$ Index: src/crypto/openssh/LICENCE =================================================================== RCS file: /home/ncvs/src/crypto/openssh/LICENCE,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 LICENCE --- src/crypto/openssh/LICENCE 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/LICENCE 30 Jun 2002 11:37:57 -0000 @@ -26,7 +26,7 @@ [However, none of that term is relevant at this point in time. All of these restrictively licenced software components which he talks about - have been removed from OpenSSH, ie. + have been removed from OpenSSH, i.e., - RSA is no longer included, found in the OpenSSL library - IDEA is no longer included, its use is deprecated @@ -85,8 +85,7 @@ 3) The 32-bit CRC compensation attack detector in deattack.c was - contributed by CORE SDI S.A. under a BSD-style license. See - http://www.core-sdi.com/english/ssh/ for details. + contributed by CORE SDI S.A. under a BSD-style license. * Cryptographic attack detector for ssh - source code * @@ -104,8 +103,83 @@ * * Ariel Futoransky * - + 4) + ssh-keygen was contributed by David Mazieres under a BSD-style + license. + + * Copyright 1995, 1996 by David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + +5) + The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers + and Paulo Barreto is in the public domain and distributed + with the following license: + + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + +6) + One component of the ssh source code is under a 4-clause BSD license, + held by the University of California, since we pulled these parts from + original Berkeley code. The Regents of the University of California + have declared that term 3 is no longer enforceable on their source code, + but we retain that license as is. + + * 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. + +7) Remaining components of the software are provided under a standard 2-term BSD licence with the following names as copyright holders: @@ -114,6 +188,10 @@ Niels Provos Dug Song Aaron Campbell + Damien Miller + Kevin Steves + Daniel Kouril + Per Allansson * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Index: src/crypto/openssh/Makefile =================================================================== RCS file: src/crypto/openssh/Makefile diff -N src/crypto/openssh/Makefile --- src/crypto/openssh/Makefile 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,14 +0,0 @@ -# $OpenBSD: Makefile,v 1.8 2001/02/04 11:11:53 djm Exp $ - -.include - -SUBDIR= lib ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server \ - ssh-keyscan sftp - -distribution: - install -C -o root -g wheel -m 0644 ${.CURDIR}/ssh_config \ - ${DESTDIR}/etc/ssh_config - install -C -o root -g wheel -m 0644 ${.CURDIR}/sshd_config \ - ${DESTDIR}/etc/sshd_config - -.include Index: src/crypto/openssh/Makefile.in =================================================================== RCS file: src/crypto/openssh/Makefile.in diff -N src/crypto/openssh/Makefile.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/Makefile.in 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,346 @@ +# $Id$ + +# uncomment if you run a non bourne compatable shell. Ie. csh +#SHELL = @SH@ + +AUTORECONF=autoreconf + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +sbindir=@sbindir@ +libexecdir=@libexecdir@ +datadir=@datadir@ +mandir=@mandir@ +mansubdir=@mansubdir@ +sysconfdir=@sysconfdir@ +piddir=@piddir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ + +DESTDIR= +VPATH=@srcdir@ +SSH_PROGRAM=@bindir@/ssh +ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass +SFTP_SERVER=$(libexecdir)/sftp-server +SSH_KEYSIGN=$(libexecdir)/ssh-keysign +RAND_HELPER=$(libexecdir)/ssh-rand-helper +PRIVSEP_PATH=@PRIVSEP_PATH@ +SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ + +PATHS= -DSSHDIR=\"$(sysconfdir)\" \ + -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ + -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ + -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ + -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ + -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ + -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \ + -DSSH_RAND_HELPER=\"$(RAND_HELPER)\" + +CC=@CC@ +LD=@LD@ +CFLAGS=@CFLAGS@ +CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ +LIBS=@LIBS@ +LIBPAM=@LIBPAM@ +LIBWRAP=@LIBWRAP@ +AR=@AR@ +RANLIB=@RANLIB@ +INSTALL=@INSTALL@ +PERL=@PERL@ +ENT=@ENT@ +XAUTH_PATH=@XAUTH_PATH@ +LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ +EXEEXT=@EXEEXT@ + +INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ +INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ + +@NO_SFTP@SFTP_PROGS=sftp-server$(EXEEXT) sftp$(EXEEXT) + +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS) + +LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o msg.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o scard-opensc.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o + +SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o + +SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth2-hostbased.o auth2-kbdint.o auth2-none.o auth2-passwd.o auth2-pubkey.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o monitor_mm.o monitor.o + +MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out +MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5 +MANTYPE = @MANTYPE@ + +CONFIGFILES=sshd_config.out ssh_config.out moduli.out +CONFIGFILES_IN=sshd_config ssh_config moduli + +PATHSUBS = \ + -D/etc/ssh/ssh_prng_cmds=$(sysconfdir)/ssh_prng_cmds \ + -D/etc/ssh/ssh_config=$(sysconfdir)/ssh_config \ + -D/etc/ssh/ssh_known_hosts=$(sysconfdir)/ssh_known_hosts \ + -D/etc/ssh/sshd_config=$(sysconfdir)/sshd_config \ + -D/usr/libexec=$(libexecdir) \ + -D/etc/shosts.equiv=$(sysconfdir)/shosts.equiv \ + -D/etc/ssh/ssh_host_key=$(sysconfdir)/ssh_host_key \ + -D/etc/ssh/ssh_host_dsa_key=$(sysconfdir)/ssh_host_dsa_key \ + -D/etc/ssh/ssh_host_rsa_key=$(sysconfdir)/ssh_host_rsa_key \ + -D/var/run/sshd.pid=$(piddir)/sshd.pid \ + -D/etc/ssh/moduli=$(sysconfdir)/moduli \ + -D/etc/ssh/sshrc=$(sysconfdir)/sshrc \ + -D/usr/X11R6/bin/xauth=$(XAUTH_PATH) \ + -D/var/empty=$(PRIVSEP_PATH) \ + -D/usr/bin:/bin:/usr/sbin:/sbin=@user_path@ + +FIXPATHSCMD = $(PERL) $(srcdir)/fixpaths $(PATHSUBS) + +all: $(CONFIGFILES) $(MANPAGES) $(TARGETS) + +$(LIBSSH_OBJS): config.h +$(SSHOBJS): config.h +$(SSHDOBJS): config.h + +.c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + +LIBCOMPAT=openbsd-compat/libopenbsd-compat.a +$(LIBCOMPAT): always + (cd openbsd-compat && $(MAKE)) +always: + +libssh.a: $(LIBSSH_OBJS) + $(AR) rv $@ $(LIBSSH_OBJS) + $(RANLIB) $@ + +ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) + $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) + $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBS) + +scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o + $(LD) -o $@ scp.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o + $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o + $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o + $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o + $(LD) -o $@ ssh-keysign.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o + $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + +sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o + $(LD) -o $@ sftp-server.o sftp-common.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o + $(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o + $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +# test driver for the loginrec code - not built by default +logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o + $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) + +$(MANPAGES): $(MANPAGES_IN) + if test "$(MANTYPE)" = "cat"; then \ + manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \ + else \ + manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \ + fi; \ + if test "$(MANTYPE)" = "man"; then \ + $(FIXPATHSCMD) $${manpage} | $(PERL) $(srcdir)/mdoc2man.pl > $@; \ + else \ + $(FIXPATHSCMD) $${manpage} > $@; \ + fi + +$(CONFIGFILES): $(CONFIGFILES_IN) + conffile=`echo $@ | sed 's/.out$$//'`; \ + $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@ + +clean: + rm -f *.o *.a $(TARGETS) logintest config.cache config.log + rm -f *.out core + (cd openbsd-compat && $(MAKE) clean) + +distclean: + rm -f *.o *.a $(TARGETS) logintest config.cache config.log + rm -f *.out core + rm -f Makefile config.h config.status ssh_prng_cmds *~ + rm -rf autom4te.cache + (cd openbsd-compat && $(MAKE) distclean) + (cd scard && $(MAKE) distclean) + +veryclean: + rm -f configure config.h.in *.0 + rm -f *.o *.a $(TARGETS) logintest config.cache config.log + rm -f *.out core + rm -f Makefile config.h config.status ssh_prng_cmds *~ + (cd openbsd-compat && $(MAKE) distclean) + (cd scard && $(MAKE) distclean) + +mrproper: distclean + +catman-do: + @for f in $(MANPAGES_IN) ; do \ + base=`echo $$f | sed 's/\..*$$//'` ; \ + echo "$$f -> $$base.0" ; \ + nroff -mandoc $$f | cat -v | sed -e 's/.\^H//g' \ + >$$base.0 ; \ + done + +distprep: catman-do + $(AUTORECONF) + (cd scard && $(MAKE) -f Makefile.in distprep) + +install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files host-key check-user +install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files + +check-user: + id $(SSH_PRIVSEP_USER) || \ + echo "WARNING: Privilege separation user \"$(SSH_PRIVSEP_USER)\" does not exist" + +scard-install: + (cd scard && $(MAKE) DESTDIR=$(DESTDIR) install) + +install-files: scard-install + $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(datadir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1 + $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5 + $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8 + $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH) + chmod 0700 $(DESTDIR)$(PRIVSEP_PATH) + $(INSTALL) -m 0755 -s ssh $(DESTDIR)$(bindir)/ssh + $(INSTALL) -m 0755 -s scp $(DESTDIR)$(bindir)/scp + $(INSTALL) -m 0755 -s ssh-add $(DESTDIR)$(bindir)/ssh-add + $(INSTALL) -m 0755 -s ssh-agent $(DESTDIR)$(bindir)/ssh-agent + $(INSTALL) -m 0755 -s ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen + $(INSTALL) -m 0755 -s ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan + $(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd + if test ! -z "$(INSTALL_SSH_RAND_HELPER)" ; then \ + $(INSTALL) -m 0755 -s ssh-rand-helper $(DESTDIR)$(libexecdir)/ssh-rand-helper ; \ + fi + $(INSTALL) -m 4711 -s ssh-keysign $(DESTDIR)$(SSH_KEYSIGN) + @NO_SFTP@$(INSTALL) -m 0755 -s sftp $(DESTDIR)$(bindir)/sftp + @NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(SFTP_SERVER) + $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 + $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 + $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 + $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 + $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 + $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 + $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 + if [ ! -z "$(INSTALL_SSH_RAND_HELPER)" ]; then \ + $(INSTALL) -m 644 ssh-rand-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 ; \ + fi + @NO_SFTP@$(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 + @NO_SFTP@$(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + -rm -f $(DESTDIR)$(bindir)/slogin + ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + ln -s ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \ + $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \ + fi + if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \ + $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \ + else \ + echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \ + fi + if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \ + $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \ + else \ + echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \ + fi + if [ -f ssh_prng_cmds -a ! -z "$(INSTALL_SSH_PRNG_CMDS)" ]; then \ + $(PERL) $(srcdir)/fixprogs ssh_prng_cmds $(ENT); \ + if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_prng_cmds ] ; then \ + $(INSTALL) -m 644 ssh_prng_cmds.out $(DESTDIR)$(sysconfdir)/ssh_prng_cmds; \ + else \ + echo "$(DESTDIR)$(sysconfdir)/ssh_prng_cmds already exists, install will not overwrite"; \ + fi ; \ + fi + if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \ + if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \ + echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \ + mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \ + else \ + $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \ + fi ; \ + else \ + echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ + fi + +host-key: ssh-keygen$(EXEEXT) + if [ -z "$(DESTDIR)" ] ; then \ + if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \ + echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \ + else \ + ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \ + fi ; \ + if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \ + echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \ + else \ + ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \ + fi ; \ + if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key ] ; then \ + echo "$(DESTDIR)$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \ + else \ + ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ; \ + fi ; \ + fi ; + +host-key-force: ssh-keygen$(EXEEXT) + ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" + ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" + ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" + +uninstallall: uninstall + -rm -f $(DESTDIR)$(sysconfdir)/ssh_config + -rm -f $(DESTDIR)$(sysconfdir)/sshd_config + -rm -f $(DESTDIR)$(sysconfdir)/ssh_prng_cmds + -rmdir $(DESTDIR)$(sysconfdir) + -rmdir $(DESTDIR)$(bindir) + -rmdir $(DESTDIR)$(sbindir) + -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1 + -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8 + -rmdir $(DESTDIR)$(mandir) + -rmdir $(DESTDIR)$(libexecdir) + +uninstall: + -rm -f $(DESTDIR)$(bindir)/slogin + -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) + -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) + -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + -rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT) + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 Index: src/crypto/openssh/Makefile.inc =================================================================== RCS file: /home/ncvs/src/crypto/openssh/Makefile.inc,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 Makefile.inc --- src/crypto/openssh/Makefile.inc 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/Makefile.inc 30 Jun 2002 11:37:57 -0000 @@ -1,8 +1,19 @@ -# $OpenBSD: Makefile.inc,v 1.13 2001/01/29 01:58:14 niklas Exp $ +# $OpenBSD: Makefile.inc,v 1.23 2002/03/06 00:23:27 markus Exp $ CFLAGS+= -I${.CURDIR}/.. -CFLAGS+= -Wall +CDIAGFLAGS= -Wall +#CDIAGFLAGS+= -Werror +CDIAGFLAGS+= -Wpointer-arith +CDIAGFLAGS+= -Wno-uninitialized +#CDIAGFLAGS+= -Wstrict-prototypes +CDIAGFLAGS+= -Wmissing-prototypes +CDIAGFLAGS+= -Wunused + +#DEBUG=-g + +#CFLAGS+= -DSMARTCARD +#LDADD+= -lsectok .include Index: src/crypto/openssh/OVERVIEW =================================================================== RCS file: /home/ncvs/src/crypto/openssh/OVERVIEW,v retrieving revision 1.1.1.1 diff -u -u -r1.1.1.1 OVERVIEW --- src/crypto/openssh/OVERVIEW 24 Feb 2000 14:29:44 -0000 1.1.1.1 +++ src/crypto/openssh/OVERVIEW 30 Jun 2002 11:37:57 -0000 @@ -1,9 +1,15 @@ +[Note: This file has not been updated for OpenSSH versions after +OpenSSH-1.2 and should be considered OBSOLETE. It has been left in +the distribution because some of its information may still be useful +to developers.] + This document is intended 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 Updated 17 Nov 1995. Updated 19 Oct 1999 for OpenSSH-1.2 +Updated 20 May 2001 note obsolete for > OpenSSH-1.2 The software consists of ssh (client), sshd (server), scp, sdist, and the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and Index: src/crypto/openssh/README =================================================================== RCS file: /home/ncvs/src/crypto/openssh/README,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 README --- src/crypto/openssh/README 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/README 30 Jun 2002 11:37:57 -0000 @@ -1,25 +1,66 @@ -This release of OpenSSH is for OpenBSD systems only. +- A Japanese translation of this document and of the OpenSSH FAQ is +- available at http://www.unixuser.org/~haruyama/security/openssh/index.html +- Thanks to HARUYAMA Seigo -Please read - http://www.openssh.com/portable.html -if you want to install OpenSSH on other operating systems. - -To extract and install this release on your OpenBSD system use: - - # cd /usr/src/usr.bin - # tar xvfz .../openssh-x.y.tgz - # cd ssh - # make obj - # make cleandir - # make depend - # make - # make install - # cp ssh_config sshd_config /etc - -OpenSSH is a derivative of the original and free ssh 1.2.12 release -by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels -Provos, Theo de Raadt and Dug Song removed many bugs, re-added newer -features and created OpenSSH. Markus Friedl contributed the support -for SSH protocol versions 1.5 and 2.0. +This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other +Unices. -See http://www.openssh.com/ for more information. +OpenSSH is based on the last free version of Tatu Ylonen's sample +implementation with all patent-encumbered algorithms removed (to +external libraries), all known security bugs fixed, new features +reintroduced and many other clean-ups. OpenSSH has been created by +Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt, +and Dug Song. It has a homepage at http://www.openssh.com/ + +This port consists of the re-introduction of autoconf support, PAM +support (for Linux and Solaris), EGD[1]/PRNGD[2] support and replacements +for OpenBSD library functions that are (regrettably) absent from other +unices. This port has been best tested on Linux, Solaris, HP-UX, NetBSD +and Irix. Support for AIX, SCO, NeXT and other Unices is underway. +This version actively tracks changes in the OpenBSD CVS repository. + +The PAM support is now more functional than the popular packages of +commercial ssh-1.2.x. It checks "account" and "session" modules for +all logins, not just when using password authentication. + +OpenSSH depends on Zlib[3], OpenSSL[4] and optionally PAM[5]. + +There is now several mailing lists for this port of OpenSSH. Please +refer to http://www.openssh.com/list.html for details on how to join. + +Please send bug reports and patches to the mailing list +openssh-unix-dev@mindrot.org. The list is open to posting by +unsubscribed users. + +If you are a citizen of an USA-embargoed country to which export of +cryptographic products is restricted, then please refrain from sending +crypto-related code or patches to the list. We cannot accept them. +Other code contribution are accepted, but please follow the OpenBSD +style guidelines[6]. + +Please refer to the INSTALL document for information on how to install +OpenSSH on your system. There are a number of differences between this +port of OpenSSH and F-Secure SSH 1.x, please refer to the OpenSSH FAQ[7] +for details and general tips. + +Damien Miller + +Miscellania - + +This version of OpenSSH is based upon code retrieved from the OpenBSD +CVS repository which in turn was based on the last free sample +implementation released by Tatu Ylonen. + +References - + +[0] http://www.openssh.com/faq.html +[1] http://www.lothar.com/tech/crypto/ +[2] http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html +[3] http://www.gzip.org/zlib/ +[4] http://www.openssl.org/ +[5] http://www.kernel.org/pub/linux/libs/pam/ (PAM is standard on Solaris + and HP-UX 11) +[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 +[7] http://www.openssh.com/faq.html + +$Id$ Index: src/crypto/openssh/README.privsep =================================================================== RCS file: src/crypto/openssh/README.privsep diff -N src/crypto/openssh/README.privsep --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/README.privsep 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,61 @@ +Privilege separation, or privsep, is method in OpenSSH by which +operations that require root privilege are performed by a separate +privileged monitor process. Its purpose is to prevent privilege +escalation by containing corruption to an unprivileged process. +More information is available at: + http://www.citi.umich.edu/u/provos/ssh/privsep.html + +Privilege separation is now enabled by default; see the +UsePrivilegeSeparation option in sshd_config(5). + +On systems which lack mmap or anonymous (MAP_ANON) memory mapping, +compression must be disabled in order for privilege separation to +function. + +When privsep is enabled, during the pre-authentication phase sshd will +chroot(2) to "/var/empty" and change its privileges to the "sshd" user +and its primary group. sshd is a pseudo-account that should not be +used by other daemons, and must be locked and should contain a +"nologin" or invalid shell. + +You should do something like the following to prepare the privsep +preauth environment: + + # mkdir /var/empty + # chown root:sys /var/empty + # chmod 755 /var/empty + # groupadd sshd + # useradd -g sshd -c 'sshd privsep' -d /var/empty -s /bin/false sshd + +/var/empty should not contain any files. + +configure supports the following options to change the default +privsep user and chroot directory: + + --with-privsep-path=xxx Path for privilege separation chroot + --with-privsep-user=user Specify non-privileged user for privilege separation + +Privsep requires operating system support for file descriptor passing. +Compression will be disabled on systems without a working mmap MAP_ANON. + +PAM-enabled OpenSSH is known to function with privsep on Linux. +It does not function on HP-UX with a trusted system +configuration. PAMAuthenticationViaKbdInt does not function with +privsep. + +Note that for a normal interactive login with a shell, enabling privsep +will require 1 additional process per login session. + +Given the following process listing (from HP-UX): + + UID PID PPID C STIME TTY TIME COMMAND + root 1005 1 0 10:45:17 ? 0:08 /opt/openssh/sbin/sshd -u0 + root 6917 1005 0 15:19:16 ? 0:00 sshd: stevesk [priv] + stevesk 6919 6917 0 15:19:17 ? 0:03 sshd: stevesk@2 + stevesk 6921 6919 0 15:19:17 pts/2 0:00 -bash + +process 1005 is the sshd process listening for new connections. +process 6917 is the privileged monitor process, 6919 is the user owned +sshd process and 6921 is the shell process. + +$Id$ Index: src/crypto/openssh/README.smartcard =================================================================== RCS file: src/crypto/openssh/README.smartcard diff -N src/crypto/openssh/README.smartcard --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/README.smartcard 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,85 @@ +How to use smartcards with OpenSSH? + +OpenSSH contains experimental support for authentication using Cyberflex +smartcards and TODOS card readers, in addition to the cards with PKCS#15 +structure supported by OpenSC. + +WARNING: Smartcard support is still in development. +Keyfile formats, etc are still subject to change. + +To enable sectok support: + +(1) install sectok: + + Sources and instructions are available from + http://www.citi.umich.edu/projects/smartcard/sectok.html + +(2) enable sectok support in OpenSSH: + + $ ./configure --with-sectok[=/path/to/libsectok] [options] + +(3) load the Java Cardlet to the Cyberflex card: + + $ sectok + sectok> login -d + sectok> jload /usr/libdata/ssh/Ssh.bin + sectok> quit + +(4) load a RSA key to the card: + + Please don't use your production RSA keys, since + with the current version of sectok/ssh-keygen + the private key file is still readable. + + $ ssh-keygen -f /path/to/rsakey -U + + In spite of the name, this does not generate a key. + It just loads an already existing key on to the card. + +(5) optional: + + Change the card password so that only you can + read the private key: + + $ sectok + sectok> login -d + sectok> setpass + sectok> quit + + This prevents reading the key but not use of the + key by the card applet. + + Do not forget the passphrase. There is no way to + recover if you do. + + IMPORTANT WARNING: If you attempt to login with the + wrong passphrase three times in a row, you will + destroy your card. + +To enable OpenSC support: + +(1) install OpenSC: + + Sources and instructions are available from + http://www.opensc.org/ + +(2) enable OpenSC support in OpenSSH: + + $ ./configure --with-opensc[=/path/to/opensc] [options] + +(3) load a RSA key to the card: + + Not supported yet. + +Common smartcard options: + +(1) tell the ssh client to use the card reader: + + $ ssh -I otherhost + +(2) or tell the agent (don't forget to restart) to use the smartcard: + + $ ssh-add -s + +-markus, +Sat Apr 13 13:48:10 EEST 2002 Index: src/crypto/openssh/TODO =================================================================== RCS file: src/crypto/openssh/TODO diff -N src/crypto/openssh/TODO --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/TODO 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,106 @@ +Programming: +- Grep for 'XXX' comments and fix + +- Link order is incorrect for some systems using Kerberos 4 and AFS. Result + is multiple inclusion of DES symbols. Holger Trapp + reports that changing the configure + generated link order from: + -lresolv -lkrb -lz -lnsl -lutil -lkafs -lkrb -ldes -lcrypto + to: + -lresolv -lkrb -lz -lnsl -lutil -lcrypto -lkafs -lkrb -ldes + fixing the problem. + +- Write a test program that calls stat() to search for EGD/PRNGd socket + rather than use the (non-portable) "test -S". + +- Replacement for setproctitle() - HP-UX support only currently + +- Handle changing passwords for the non-PAM expired password case + +- Improve PAM support (a pam_lastlog module will cause sshd to exit) + and maybe support alternate forms of authenications like OPIE via + pam? + +- Rework PAM ChallengeResponseAuthentication + - Use kbdint request packet with 0 prompts for informational messages + - Use different PAM service name for kbdint vs regular auth (suggest from + Solar Designer) + - Ability to select which ChallengeResponseAuthentications may be used + and order to try them in e.g. "ChallengeResponseAuthentication skey, pam" + +- Complete Tru64 SIA support + - It looks like we could merge it into the password auth code to cut down + on diff size. Maybe PAM password auth too? + +- Finish integrating kernel-level auditing code for IRIX and SOLARIS + (Gilbert.r.loomis@saic.com) + +- sftp-server: Rework to step down to 32bit ints if the platform + lacks 'long long' == 64bit (Notable SCO w/ SCO compiler) + +- Linux hangs for 20 seconds when you do "sleep 20&exit". All current + solutions break scp or leaves processes hanging around after the ssh + connection has ended. It seems to be linked to two things. One + select() under Linux is not as nice as others, and two the children + of the shell are not killed on exiting the shell. Redhat have an excellent + description of this in their RPM package. + +- Build an automated test suite + +- 64-bit builds on HP-UX 11.X (stevesk@pobox.com): + - utmp/wtmp get corrupted (something in loginrec?) + - can't build with PAM (no 64-bit libpam yet) + +Documentation: +- More and better + +- Install FAQ? + +- General FAQ on S/Key, TIS, RSA, RSA2, DSA, etc and suggestions on when it + would be best to use them. + +- Create a Documentation/ directory? + +Clean up configure/makefiles: +- Clean up configure.ac - There are a few double #defined variables + left to do. HAVE_LOGIN is one of them. Consider NOT looking for + information in wtmpx or utmpx or any of that stuff if it's not detected + from the start + +- Fails to compile when cross compile. + (vinschen@redhat.com) + +- Replace the whole u_intXX_t evilness in acconfig.h with something better??? + +- Consider splitting the u_intXX_t test for sys/bitype.h into seperate test + to allow people to (right/wrongfully) link against Bind directly. + +- Consider splitting configure.ac into seperate files which do logically + similar tests. E.g move all the type detection stuff into one file, + entropy related stuff into another. + +Packaging: +- Solaris: Update packaging scripts and build new sysv startup scripts + Ideally the package metadata should be generated by autoconf. + (gilbert.r.loomis@saic.com) + +- HP-UX: Provide DEPOT package scripts. + (gilbert.r.loomis@saic.com) + + +PrivSep Issues: +- mmap() issues. + + /dev/zero solution (Solaris) + + No/broken MAP_ANON (Irix) + + broken /dev/zero parse (Linux) +- PAM + + See above PAM notes +- AIX + + usrinfo() does not set TTY, but only required for legicy systems. Works + with PrivSep. +- OSF + + SIA is broken +- Cygwin + + Privsep for Pre-auth only (no fd passing) + +$Id$ Index: src/crypto/openssh/WARNING.RNG =================================================================== RCS file: src/crypto/openssh/WARNING.RNG diff -N src/crypto/openssh/WARNING.RNG --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/WARNING.RNG 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,96 @@ +This document contains a description of portable OpenSSH's random +number collection code. An alternate reading of this text could +well be titled "Why I should pressure my system vendor to supply +/dev/random in their OS". + +Why is this important? OpenSSH depends on good, unpredictable numbers +for generating keys, performing digital signatures and forming +cryptographic challenges. If the random numbers that it uses are +predictable, then the strength of the whole system is compromised. + +A particularly pernicious problem arises with DSA keys (used by the +ssh2 protocol). Performing a DSA signature (which is required for +authentication), entails the use of a 160 bit random number. If an +attacker can predict this number, then they can deduce your *private* +key and impersonate you or your hosts. + +If you are using the builtin random number support (configure will +tell you if this is the case), then read this document in its entirety. +Alternately, you can use Lutz Jaenicke's PRNGd - a small daemon which +collects random numbers and makes them available by a socket. + +Please also request that your OS vendor provides a kernel-based random +number collector (/dev/random) in future versions of your operating +systems by default. + +On to the description... + +The portable OpenSSH contains random number collection support for +systems which lack a kernel entropy pool (/dev/random). + +This collector (as of 3.1 and beyond) comes as an external application +that allows the local admin to decide on how to implement entropy +collection. + +The default entropy collector operates by executing the programs listed +in ($etcdir)/ssh_prng_cmds, reading their output and adding it to the +PRNG supplied by OpenSSL (which is hash-based). It also stirs in the +output of several system calls and timings from the execution of the +programs that it runs. + +The ssh_prng_cmds file also specifies a 'rate' for each program. This +represents the number of bits of randomness per byte of output from +the specified program. + +The random number code will also read and save a seed file to +~/.ssh/prng_seed. This contents of this file are added to the random +number generator at startup. The goal here is to maintain as much +randomness between sessions as possible. + +The default entropy collection code has two main problems: + +1. It is slow. + +Executing each program in the list can take a large amount of time, +especially on slower machines. Additionally some program can take a +disproportionate time to execute. + +Tuning the default entropy collection code is difficult at this point. +It requires doing 'times ./ssh-rand-helper' and modifying the +($etcdir)/ssh_prng_cmds until you have found the issue. In the next +release we will be looking at support '-v' for verbose output to allow +easier debugging. + +The default entropy collector will timeout programs which take too long +to execute, the actual timeout used can be adjusted with the +--with-entropy-timeout configure option. OpenSSH will not try to +re-execute programs which have not been found, have had a non-zero +exit status or have timed out more than a couple of times. + +2. Estimating the real 'rate' of program outputs is non-trivial + +The shear volume of the task is problematic: there are currently +around 50 commands in the ssh_prng_cmds list, portable OpenSSH +supports at least 12 different OSs. That is already 600 sets of data +to be analysed, without taking into account the numerous differences +between versions of each OS. + +On top of this, the different commands can produce varying amounts of +usable data depending on how busy the machine is, how long it has been +up and various other factors. + +To make matters even more complex, some of the commands are reporting +largely the same data as other commands (eg. the various "ps" calls). + + +How to avoid the default entropy code? + +The best way is to read the OpenSSL documentation and recompile OpenSSL +to use prngd or egd. Some platforms (like earily solaris) have 3rd +party /dev/random devices that can be also used for this task. + +If you are forced to use ssh-rand-helper consider still downloading +prngd/egd and configure OpenSSH using --with-prngd-port=xx or +--with-prngd-socket=xx (refer to INSTALL for more information). + +$Id$ Index: src/crypto/openssh/acconfig.h =================================================================== RCS file: src/crypto/openssh/acconfig.h diff -N src/crypto/openssh/acconfig.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/acconfig.h 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,372 @@ +/* $Id$ */ +/* $FreeBSD: src/crypto/openssh/acconfig.h,v 1.3 2002/06/29 11:48:58 des Exp $ */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +/* Generated automatically from acconfig.h by autoheader. */ +/* Please make your changes there */ + +@TOP@ + +/* Define to a Set Process Title type if your system is */ +/* supported by bsd-setproctitle.c */ +#undef SPT_TYPE + +/* setgroups() NOOP allowed */ +#undef SETGROUPS_NOOP + +/* SCO workaround */ +#undef BROKEN_SYS_TERMIO_H + +/* Define if you have SecureWare-based protected password database */ +#undef HAVE_SECUREWARE + +/* If your header files don't define LOGIN_PROGRAM, then use this (detected) */ +/* from environment and PATH */ +#undef LOGIN_PROGRAM_FALLBACK + +/* Define if your password has a pw_class field */ +#undef HAVE_PW_CLASS_IN_PASSWD + +/* Define if your password has a pw_expire field */ +#undef HAVE_PW_EXPIRE_IN_PASSWD + +/* Define if your password has a pw_change field */ +#undef HAVE_PW_CHANGE_IN_PASSWD + +/* Define if your system uses access rights style file descriptor passing */ +#undef HAVE_ACCRIGHTS_IN_MSGHDR + +/* Define if your system uses ancillary data style file descriptor passing */ +#undef HAVE_CONTROL_IN_MSGHDR + +/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ +#undef BROKEN_INET_NTOA + +/* Define if your system defines sys_errlist[] */ +#undef HAVE_SYS_ERRLIST + +/* Define if your system defines sys_nerr */ +#undef HAVE_SYS_NERR + +/* Define if your system choked on IP TOS setting */ +#undef IP_TOS_IS_BROKEN + +/* Define if you have the getuserattr function. */ +#undef HAVE_GETUSERATTR + +/* Work around problematic Linux PAM modules handling of PAM_TTY */ +#undef PAM_TTY_KLUDGE + +/* Use PIPES instead of a socketpair() */ +#undef USE_PIPES + +/* Define if your snprintf is busted */ +#undef BROKEN_SNPRINTF + +/* Define if you are on Cygwin */ +#undef HAVE_CYGWIN + +/* Define if you have a broken realpath. */ +#undef BROKEN_REALPATH + +/* Define if you are on NeXT */ +#undef HAVE_NEXT + +/* Define if you are on NEWS-OS */ +#undef HAVE_NEWS4 + +/* Define if you want to enable PAM support */ +#undef USE_PAM + +/* Define if you want to enable AIX4's authenticate function */ +#undef WITH_AIXAUTHENTICATE + +/* Define if you have/want arrays (cluster-wide session managment, not C arrays) */ +#undef WITH_IRIX_ARRAY + +/* Define if you want IRIX project management */ +#undef WITH_IRIX_PROJECT + +/* Define if you want IRIX audit trails */ +#undef WITH_IRIX_AUDIT + +/* Define if you want IRIX kernel jobs */ +#undef WITH_IRIX_JOBS + +/* Location of PRNGD/EGD random number socket */ +#undef PRNGD_SOCKET + +/* Port number of PRNGD/EGD random number socket */ +#undef PRNGD_PORT + +/* Builtin PRNG command timeout */ +#undef ENTROPY_TIMEOUT_MSEC + +/* non-privileged user for privilege separation */ +#undef SSH_PRIVSEP_USER + +/* Define if you want to install preformatted manpages.*/ +#undef MANTYPE + +/* Define if your ssl headers are included with #include */ +#undef HAVE_OPENSSL + +/* Define if you are linking against RSAref. Used only to print the right + * message at run-time. */ +#undef RSAREF + +/* struct timeval */ +#undef HAVE_STRUCT_TIMEVAL + +/* struct utmp and struct utmpx fields */ +#undef HAVE_HOST_IN_UTMP +#undef HAVE_HOST_IN_UTMPX +#undef HAVE_ADDR_IN_UTMP +#undef HAVE_ADDR_IN_UTMPX +#undef HAVE_ADDR_V6_IN_UTMP +#undef HAVE_ADDR_V6_IN_UTMPX +#undef HAVE_SYSLEN_IN_UTMPX +#undef HAVE_PID_IN_UTMP +#undef HAVE_TYPE_IN_UTMP +#undef HAVE_TYPE_IN_UTMPX +#undef HAVE_TV_IN_UTMP +#undef HAVE_TV_IN_UTMPX +#undef HAVE_ID_IN_UTMP +#undef HAVE_ID_IN_UTMPX +#undef HAVE_EXIT_IN_UTMP +#undef HAVE_TIME_IN_UTMP +#undef HAVE_TIME_IN_UTMPX + +/* Define if you don't want to use your system's login() call */ +#undef DISABLE_LOGIN + +/* Define if you don't want to use pututline() etc. to write [uw]tmp */ +#undef DISABLE_PUTUTLINE + +/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */ +#undef DISABLE_PUTUTXLINE + +/* Define if you don't want to use lastlog */ +#undef DISABLE_LASTLOG + +/* Define if you don't want to use utmp */ +#undef DISABLE_UTMP + +/* Define if you don't want to use utmpx */ +#undef DISABLE_UTMPX + +/* Define if you don't want to use wtmp */ +#undef DISABLE_WTMP + +/* Define if you don't want to use wtmpx */ +#undef DISABLE_WTMPX + +/* Some systems need a utmpx entry for /bin/login to work */ +#undef LOGIN_NEEDS_UTMPX + +/* Some versions of /bin/login need the TERM supplied on the commandline */ +#undef LOGIN_NEEDS_TERM + +/* Define if your login program cannot handle end of options ("--") */ +#undef LOGIN_NO_ENDOPT + +/* Define if you want to specify the path to your lastlog file */ +#undef CONF_LASTLOG_FILE + +/* Define if you want to specify the path to your utmp file */ +#undef CONF_UTMP_FILE + +/* Define if you want to specify the path to your wtmp file */ +#undef CONF_WTMP_FILE + +/* Define if you want to specify the path to your utmpx file */ +#undef CONF_UTMPX_FILE + +/* Define if you want to specify the path to your wtmpx file */ +#undef CONF_WTMPX_FILE + +/* Define if you want external askpass support */ +#undef USE_EXTERNAL_ASKPASS + +/* Define if libc defines __progname */ +#undef HAVE___PROGNAME + +/* Define if compiler implements __FUNCTION__ */ +#undef HAVE___FUNCTION__ + +/* Define if compiler implements __func__ */ +#undef HAVE___func__ + +/* Define if you want Kerberos 5 support */ +#undef KRB5 + +/* Define this if you are using the Heimdal version of Kerberos V5 */ +#undef HEIMDAL + +/* Define if you want Kerberos 4 support */ +#undef KRB4 + +/* Define if you want AFS support */ +#undef AFS + +/* Define if you want S/Key support */ +#undef SKEY + +/* Define if you want OPIE support */ +#undef OPIE + +/* Define if you want TCP Wrappers support */ +#undef LIBWRAP + +/* Define if your libraries define login() */ +#undef HAVE_LOGIN + +/* Define if your libraries define daemon() */ +#undef HAVE_DAEMON + +/* Define if your libraries define getpagesize() */ +#undef HAVE_GETPAGESIZE + +/* Define if xauth is found in your path */ +#undef XAUTH_PATH + +/* Define if you want to allow MD5 passwords */ +#undef HAVE_MD5_PASSWORDS + +/* Define if you want to disable shadow passwords */ +#undef DISABLE_SHADOW + +/* Define if you want to use shadow password expire field */ +#undef HAS_SHADOW_EXPIRE + +/* Define if you have Digital Unix Security Integration Architecture */ +#undef HAVE_OSF_SIA + +/* Define if you have getpwanam(3) [SunOS 4.x] */ +#undef HAVE_GETPWANAM + +/* Define if you have an old version of PAM which takes only one argument */ +/* to pam_strerror */ +#undef HAVE_OLD_PAM + +/* Define if you are using Solaris-derived PAM which passes pam_messages */ +/* to the conversation function with an extra level of indirection */ +#undef PAM_SUN_CODEBASE + +/* Set this to your mail directory if you don't have maillock.h */ +#undef MAIL_DIRECTORY + +/* Data types */ +#undef HAVE_U_INT +#undef HAVE_INTXX_T +#undef HAVE_U_INTXX_T +#undef HAVE_UINTXX_T +#undef HAVE_INT64_T +#undef HAVE_U_INT64_T +#undef HAVE_U_CHAR +#undef HAVE_SIZE_T +#undef HAVE_SSIZE_T +#undef HAVE_CLOCK_T +#undef HAVE_MODE_T +#undef HAVE_PID_T +#undef HAVE_SA_FAMILY_T +#undef HAVE_STRUCT_SOCKADDR_STORAGE +#undef HAVE_STRUCT_ADDRINFO +#undef HAVE_STRUCT_IN6_ADDR +#undef HAVE_STRUCT_SOCKADDR_IN6 + +/* Fields in struct sockaddr_storage */ +#undef HAVE_SS_FAMILY_IN_SS +#undef HAVE___SS_FAMILY_IN_SS + +/* Define if you have /dev/ptmx */ +#undef HAVE_DEV_PTMX + +/* Define if you have /dev/ptc */ +#undef HAVE_DEV_PTS_AND_PTC + +/* Define if you need to use IP address instead of hostname in $DISPLAY */ +#undef IPADDR_IN_DISPLAY + +/* Specify default $PATH */ +#undef USER_PATH + +/* Specify location of ssh.pid */ +#undef _PATH_SSH_PIDDIR + +/* Use IPv4 for connection by default, IPv6 can still if explicity asked */ +#undef IPV4_DEFAULT + +/* getaddrinfo is broken (if present) */ +#undef BROKEN_GETADDRINFO + +/* Workaround more Linux IPv6 quirks */ +#undef DONT_TRY_OTHER_AF + +/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */ +#undef IPV4_IN_IPV6 + +/* Define if you have BSD auth support */ +#undef BSD_AUTH + +/* Define if X11 doesn't support AF_UNIX sockets on that system */ +#undef NO_X11_UNIX_SOCKETS + +/* Needed for SCO and NeXT */ +#undef BROKEN_SAVED_UIDS + +/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */ +#undef GLOB_HAS_ALTDIRFUNC + +/* Define if your system glob() function has gl_matchc options in glob_t */ +#undef GLOB_HAS_GL_MATCHC + +/* Define in your struct dirent expects you to allocate extra space for d_name */ +#undef BROKEN_ONE_BYTE_DIRENT_D_NAME + +/* Define if your getopt(3) defines and uses optreset */ +#undef HAVE_GETOPT_OPTRESET + +/* Define on *nto-qnx systems */ +#undef MISSING_NFDBITS + +/* Define on *nto-qnx systems */ +#undef MISSING_HOWMANY + +/* Define on *nto-qnx systems */ +#undef MISSING_FD_MASK + +/* Define if you want smartcard support */ +#undef SMARTCARD + +/* Define if you want smartcard support using sectok */ +#undef USE_SECTOK + +/* Define if you want smartcard support using OpenSC */ +#undef USE_OPENSC + +/* Define if you want to use OpenSSL's internally seeded PRNG only */ +#undef OPENSSL_PRNG_ONLY + +/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ +#undef WITH_ABBREV_NO_TTY + +/* Define if you want a different $PATH for the superuser */ +#undef SUPERUSER_PATH + +/* Path that unprivileged child will chroot() to in privep mode */ +#undef PRIVSEP_PATH + +/* Define if you have the `mmap' function that supports MAP_ANON|SHARED */ +#undef HAVE_MMAP_ANON_SHARED + +/* Define if sendmsg()/recvmsg() has problems passing file descriptors */ +#undef BROKEN_FD_PASSING + +@BOTTOM@ + +/* ******************* Shouldn't need to edit below this line ************** */ + +#endif /* _CONFIG_H */ Index: src/crypto/openssh/aclocal.m4 =================================================================== RCS file: src/crypto/openssh/aclocal.m4 diff -N src/crypto/openssh/aclocal.m4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/aclocal.m4 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,86 @@ +dnl $Id$ +dnl +dnl OpenSSH-specific autoconf macros +dnl + + +dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol) +dnl Does AC_EGREP_HEADER on 'header' for the string 'field' +dnl If found, set 'symbol' to be defined. Cache the result. +dnl TODO: This is not foolproof, better to compile and read from there +AC_DEFUN(OSSH_CHECK_HEADER_FOR_FIELD, [ +# look for field '$1' in header '$2' + dnl This strips characters illegal to m4 from the header filename + ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'` + dnl + ossh_varname="ossh_cv_$ossh_safe""_has_"$1 + AC_MSG_CHECKING(for $1 field in $2) + AC_CACHE_VAL($ossh_varname, [ + AC_EGREP_HEADER($1, $2, [ dnl + eval "$ossh_varname=yes" dnl + ], [ dnl + eval "$ossh_varname=no" dnl + ]) dnl + ]) + ossh_result=`eval 'echo $'"$ossh_varname"` + if test -n "`echo $ossh_varname`"; then + AC_MSG_RESULT($ossh_result) + if test "x$ossh_result" = "xyes"; then + AC_DEFINE($3) + fi + else + AC_MSG_RESULT(no) + fi +]) + +dnl OSSH_PATH_ENTROPY_PROG(variablename, command): +dnl Tidiness function, sets 'undef' if not found, and does the AC_SUBST +AC_DEFUN(OSSH_PATH_ENTROPY_PROG, [ + AC_PATH_PROG($1, $2) + if test -z "[$]$1" ; then + $1="undef" + fi + AC_SUBST($1) +]) + +dnl Check for socklen_t: historically on BSD it is an int, and in +dnl POSIX 1g it is a type of its own, but some platforms use different +dnl types for the argument to getsockopt, getpeername, etc. So we +dnl have to test to find something that will work. +AC_DEFUN([TYPE_SOCKLEN_T], +[ + AC_CHECK_TYPE([socklen_t], ,[ + AC_MSG_CHECKING([for socklen_t equivalent]) + AC_CACHE_VAL([curl_cv_socklen_t_equiv], + [ + # Systems have either "struct sockaddr *" or + # "void *" as the second argument to getpeername + curl_cv_socklen_t_equiv= + for arg2 in "struct sockaddr" void; do + for t in int size_t unsigned long "unsigned long"; do + AC_TRY_COMPILE([ + #include + #include + + int getpeername (int, $arg2 *, $t *); + ],[ + $t len; + getpeername(0,0,&len); + ],[ + curl_cv_socklen_t_equiv="$t" + break + ]) + done + done + + if test "x$curl_cv_socklen_t_equiv" = x; then + AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) + fi + ]) + AC_MSG_RESULT($curl_cv_socklen_t_equiv) + AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv, + [type to use in place of socklen_t if not defined])], + [#include +#include ]) +]) + Index: src/crypto/openssh/atomicio.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/atomicio.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 atomicio.c --- src/crypto/openssh/atomicio.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/atomicio.c 30 Jun 2002 11:37:57 -0000 @@ -24,9 +24,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: atomicio.c,v 1.9 2001/03/02 18:54:30 deraadt Exp $"); +RCSID("$OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp $"); -#include "xmalloc.h" #include "atomicio.h" /* @@ -46,7 +45,11 @@ res = (f) (fd, s + pos, n - pos); switch (res) { case -1: +#ifdef EWOULDBLOCK + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) +#else if (errno == EINTR || errno == EAGAIN) +#endif continue; case 0: return (res); Index: src/crypto/openssh/atomicio.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/atomicio.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 atomicio.h --- src/crypto/openssh/atomicio.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/atomicio.h 30 Jun 2002 11:37:57 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.h,v 1.3 2001/03/02 18:54:30 deraadt Exp $ */ +/* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $ */ /* * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. @@ -28,4 +28,4 @@ /* * Ensure all of data on socket comes through. f==read || f==write */ -ssize_t atomicio(ssize_t (*f)(), int fd, void *s, size_t n); +ssize_t atomicio(ssize_t (*)(), int, void *, size_t); Index: src/crypto/openssh/auth-bsdauth.c =================================================================== RCS file: src/crypto/openssh/auth-bsdauth.c diff -N src/crypto/openssh/auth-bsdauth.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth-bsdauth.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "includes.h" +RCSID("$OpenBSD: auth-bsdauth.c,v 1.4 2002/06/19 00:27:55 deraadt Exp $"); + +#ifdef BSD_AUTH +#include "xmalloc.h" +#include "auth.h" +#include "log.h" +#include "monitor_wrap.h" + +static void * +bsdauth_init_ctx(Authctxt *authctxt) +{ + return authctxt; +} + +int +bsdauth_query(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on) +{ + Authctxt *authctxt = ctx; + char *challenge = NULL; + + if (authctxt->as != NULL) { + debug2("bsdauth_query: try reuse session"); + challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); + if (challenge == NULL) { + auth_close(authctxt->as); + authctxt->as = NULL; + } + } + + if (challenge == NULL) { + debug2("bsdauth_query: new bsd auth session"); + debug3("bsdauth_query: style %s", + authctxt->style ? authctxt->style : ""); + authctxt->as = auth_userchallenge(authctxt->user, + authctxt->style, "auth-ssh", &challenge); + if (authctxt->as == NULL) + challenge = NULL; + debug2("bsdauth_query: <%s>", challenge ? challenge : "empty"); + } + + if (challenge == NULL) + return -1; + + *name = xstrdup(""); + *infotxt = xstrdup(""); + *numprompts = 1; + *prompts = xmalloc(*numprompts * sizeof(char*)); + *echo_on = xmalloc(*numprompts * sizeof(u_int)); + (*echo_on)[0] = 0; + (*prompts)[0] = xstrdup(challenge); + + return 0; +} + +int +bsdauth_respond(void *ctx, u_int numresponses, char **responses) +{ + Authctxt *authctxt = ctx; + int authok; + + if (authctxt->as == 0) + error("bsdauth_respond: no bsd auth session"); + + if (numresponses != 1) + return -1; + + authok = auth_userresponse(authctxt->as, responses[0], 0); + authctxt->as = NULL; + debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok); + + return (authok == 0) ? -1 : 0; +} + +static void +bsdauth_free_ctx(void *ctx) +{ + Authctxt *authctxt = ctx; + + if (authctxt && authctxt->as) { + auth_close(authctxt->as); + authctxt->as = NULL; + } +} + +KbdintDevice bsdauth_device = { + "bsdauth", + bsdauth_init_ctx, + bsdauth_query, + bsdauth_respond, + bsdauth_free_ctx +}; + +KbdintDevice mm_bsdauth_device = { + "bsdauth", + bsdauth_init_ctx, + mm_bsdauth_query, + mm_bsdauth_respond, + bsdauth_free_ctx +}; +#endif Index: src/crypto/openssh/auth-chall.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-chall.c,v retrieving revision 1.2.2.2 diff -u -u -r1.2.2.2 auth-chall.c --- src/crypto/openssh/auth-chall.c 25 Apr 2002 16:53:50 -0000 1.2.2.2 +++ src/crypto/openssh/auth-chall.c 30 Jun 2002 11:37:57 -0000 @@ -23,83 +23,60 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-chall.c,v 1.7 2001/04/05 10:42:47 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth-chall.c,v 1.2.2.2 2002/04/25 16:53:50 des Exp $"); +RCSID("$OpenBSD: auth-chall.c,v 1.8 2001/05/18 14:13:28 markus Exp $"); #include "auth.h" #include "log.h" +#include "xmalloc.h" -#ifdef BSD_AUTH -char * -get_challenge(Authctxt *authctxt, char *devs) -{ - char *challenge; +/* limited protocol v1 interface to kbd-interactive authentication */ - if (authctxt->as != NULL) { - debug2("try reuse session"); - challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); - if (challenge != NULL) { - debug2("reuse bsd auth session"); - return challenge; - } - auth_close(authctxt->as); - authctxt->as = NULL; - } - debug2("new bsd auth session"); - if (devs == NULL || strlen(devs) == 0) - devs = authctxt->style; - debug3("bsd auth: devs %s", devs ? devs : ""); - authctxt->as = auth_userchallenge(authctxt->user, devs, "auth-ssh", - &challenge); - if (authctxt->as == NULL) - return NULL; - debug2("get_challenge: <%s>", challenge ? challenge : "EMPTY"); - return challenge; -} -int -verify_response(Authctxt *authctxt, char *response) -{ - int authok; - - if (authctxt->as == 0) - error("verify_response: no bsd auth session"); - authok = auth_userresponse(authctxt->as, response, 0); - authctxt->as = NULL; - debug("verify_response: <%s> = <%d>", response, authok); - return authok != 0; -} -#else -#ifdef SKEY -#include +extern KbdintDevice *devices[]; +static KbdintDevice *device; char * -get_challenge(Authctxt *authctxt, char *devs) +get_challenge(Authctxt *authctxt) { - static char challenge[1024]; - struct opie opie; - if (opiechallenge(&opie, authctxt->user, challenge) != 0) + char *challenge, *name, *info, **prompts; + u_int i, numprompts; + u_int *echo_on; + + device = devices[0]; /* we always use the 1st device for protocol 1 */ + if (device == NULL) return NULL; - strlcat(challenge, "\nS/Key Password: ", sizeof challenge); - return challenge; -} -int -verify_response(Authctxt *authctxt, char *response) -{ - return (authctxt->valid && - opie_haskey(authctxt->pw->pw_name) == 0 && - opie_passverify(authctxt->pw->pw_name, response) != -1); -} -#else -/* not available */ -char * -get_challenge(Authctxt *authctxt, char *devs) -{ - return NULL; + if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL) + return NULL; + if (device->query(authctxt->kbdintctxt, &name, &info, + &numprompts, &prompts, &echo_on)) { + device->free_ctx(authctxt->kbdintctxt); + authctxt->kbdintctxt = NULL; + return NULL; + } + if (numprompts < 1) + fatal("get_challenge: numprompts < 1"); + challenge = xstrdup(prompts[0]); + for (i = 0; i < numprompts; i++) + xfree(prompts[i]); + xfree(prompts); + xfree(name); + xfree(echo_on); + xfree(info); + + return (challenge); } int -verify_response(Authctxt *authctxt, char *response) +verify_response(Authctxt *authctxt, const char *response) { - return 0; + char *resp[1]; + int res; + + if (device == NULL) + return 0; + if (authctxt->kbdintctxt == NULL) + return 0; + resp[0] = (char *)response; + res = device->respond(authctxt->kbdintctxt, 1, resp); + device->free_ctx(authctxt->kbdintctxt); + authctxt->kbdintctxt = NULL; + return res ? 0 : 1; } -#endif -#endif Index: src/crypto/openssh/auth-krb4.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-krb4.c,v retrieving revision 1.2.2.5 diff -u -u -r1.2.2.5 auth-krb4.c --- src/crypto/openssh/auth-krb4.c 28 Sep 2001 01:33:33 -0000 1.2.2.5 +++ src/crypto/openssh/auth-krb4.c 30 Jun 2002 11:37:57 -0000 @@ -23,8 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-krb4.c,v 1.23 2001/01/22 08:15:00 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth-krb4.c,v 1.2.2.5 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: auth-krb4.c,v 1.27 2002/06/11 05:46:20 mpech Exp $"); #include "ssh.h" #include "ssh1.h" @@ -32,6 +31,7 @@ #include "xmalloc.h" #include "log.h" #include "servconf.h" +#include "uidswap.h" #include "auth.h" #ifdef AFS @@ -39,48 +39,92 @@ #endif #ifdef KRB4 -char *ticket = NULL; - extern ServerOptions options; +static int +krb4_init(void *context) +{ + static int cleanup_registered = 0; + Authctxt *authctxt = (Authctxt *)context; + const char *tkt_root = TKT_ROOT; + struct stat st; + int fd; + + if (!authctxt->krb4_ticket_file) { + /* Set unique ticket string manually since we're still root. */ + authctxt->krb4_ticket_file = xmalloc(MAXPATHLEN); +#ifdef AFS + if (lstat("/ticket", &st) != -1) + tkt_root = "/ticket/"; +#endif /* AFS */ + snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%ld", + tkt_root, authctxt->pw->pw_uid, (long)getpid()); + krb_set_tkt_string(authctxt->krb4_ticket_file); + } + /* Register ticket cleanup in case of fatal error. */ + if (!cleanup_registered) { + fatal_add_cleanup(krb4_cleanup_proc, authctxt); + cleanup_registered = 1; + } + /* Try to create our ticket file. */ + if ((fd = mkstemp(authctxt->krb4_ticket_file)) != -1) { + close(fd); + return (1); + } + /* Ticket file exists - make sure user owns it (just passed ticket). */ + if (lstat(authctxt->krb4_ticket_file, &st) != -1) { + if (st.st_mode == (S_IFREG | S_IRUSR | S_IWUSR) && + st.st_uid == authctxt->pw->pw_uid) + return (1); + } + /* Failure - cancel cleanup function, leaving ticket for inspection. */ + log("WARNING: bad ticket file %s", authctxt->krb4_ticket_file); + + fatal_remove_cleanup(krb4_cleanup_proc, authctxt); + cleanup_registered = 0; + + xfree(authctxt->krb4_ticket_file); + authctxt->krb4_ticket_file = NULL; + + return (0); +} + /* * try krb4 authentication, * return 1 on success, 0 on failure, -1 if krb4 is not available */ - int -auth_krb4_password(struct passwd * pw, const char *password) +auth_krb4_password(Authctxt *authctxt, const char *password) { AUTH_DAT adata; KTEXT_ST tkt; struct hostent *hp; - u_long faddr; - char localhost[MAXHOSTNAMELEN]; - char phost[INST_SZ]; - char realm[REALM_SZ]; + struct passwd *pw; + char localhost[MAXHOSTNAMELEN], phost[INST_SZ], realm[REALM_SZ]; + u_int32_t faddr; int r; + if ((pw = authctxt->pw) == NULL) + return (0); + /* * 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 (!krb4_init(pw->pw_uid)) { + if (!krb4_init(authctxt)) { log("Couldn't initialize Kerberos ticket file for %s!", pw->pw_name); - goto kerberos_auth_failure; + goto failure; } /* Try to get TGT using our password. */ - r = krb_get_pw_in_tkt((char *) pw->pw_name, "", - realm, "krbtgt", realm, - DEFAULT_TKT_LIFE, (char *) password); + r = krb_get_pw_in_tkt((char *) pw->pw_name, "", realm, + "krbtgt", realm, DEFAULT_TKT_LIFE, (char *)password); if (r != INTK_OK) { - packet_send_debug("Kerberos V4 password " - "authentication for %s failed: %s", - pw->pw_name, krb_err_txt[r]); - goto kerberos_auth_failure; + debug("Kerberos v4 password authentication for %s " + "failed: %s", pw->pw_name, krb_err_txt[r]); + goto failure; } /* Successful authentication. */ chown(tkt_string(), pw->pw_uid, pw->pw_gid); @@ -90,17 +134,17 @@ * "rcmd" ticket to ensure that we are not talking * to a bogus Kerberos server. */ - (void) gethostname(localhost, sizeof(localhost)); - (void) strlcpy(phost, (char *) krb_get_phost(localhost), - INST_SZ); + gethostname(localhost, sizeof(localhost)); + strlcpy(phost, (char *)krb_get_phost(localhost), + sizeof(phost)); r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33); if (r == KSUCCESS) { - if (!(hp = gethostbyname(localhost))) { + if ((hp = gethostbyname(localhost)) == NULL) { log("Couldn't get local host address!"); - goto kerberos_auth_failure; + goto failure; } - memmove((void *) &faddr, (void *) hp->h_addr, + memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr)); /* Verify our "rcmd" ticket. */ @@ -111,116 +155,71 @@ * Probably didn't have a srvtab on * localhost. Disallow login. */ - log("Kerberos V4 TGT for %s unverifiable, " + log("Kerberos v4 TGT for %s unverifiable, " "no srvtab installed? krb_rd_req: %s", pw->pw_name, krb_err_txt[r]); - goto kerberos_auth_failure; + goto failure; } else if (r != KSUCCESS) { - log("Kerberos V4 %s ticket unverifiable: %s", + log("Kerberos v4 %s ticket unverifiable: %s", KRB4_SERVICE_NAME, krb_err_txt[r]); - goto kerberos_auth_failure; + goto failure; } } else if (r == KDC_PR_UNKNOWN) { /* * Disallow login if no rcmd service exists, and * log the error. */ - log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s " + log("Kerberos v4 TGT for %s unverifiable: %s; %s.%s " "not registered, or srvtab is wrong?", pw->pw_name, - krb_err_txt[r], KRB4_SERVICE_NAME, phost); - goto kerberos_auth_failure; + krb_err_txt[r], KRB4_SERVICE_NAME, phost); + goto failure; } else { /* * TGT is bad, forget it. Possibly spoofed! */ - packet_send_debug("WARNING: Kerberos V4 TGT " - "possibly spoofed for %s: %s", - pw->pw_name, krb_err_txt[r]); - goto kerberos_auth_failure; + debug("WARNING: Kerberos v4 TGT possibly spoofed " + "for %s: %s", pw->pw_name, krb_err_txt[r]); + goto failure; } - /* Authentication succeeded. */ - return 1; + return (1); + } else + /* Logging in as root or no local Kerberos realm. */ + debug("Unable to authenticate to Kerberos."); -kerberos_auth_failure: - krb4_cleanup_proc(NULL); + failure: + krb4_cleanup_proc(authctxt); + + if (!options.kerberos_or_local_passwd) + return (0); - if (!options.krb4_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. */ - return -1; + return (-1); } void -krb4_cleanup_proc(void *ignore) +krb4_cleanup_proc(void *context) { + Authctxt *authctxt = (Authctxt *)context; debug("krb4_cleanup_proc called"); - if (ticket) { + if (authctxt->krb4_ticket_file) { (void) dest_tkt(); - xfree(ticket); - ticket = NULL; - } -} - -int -krb4_init(uid_t uid) -{ - static int cleanup_registered = 0; - const char *tkt_root = TKT_ROOT; - struct stat st; - int fd; - - if (!ticket) { - /* 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 */ - snprintf(ticket, MAXPATHLEN, "%s%u_%d", tkt_root, uid, getpid()); - (void) krb_set_tkt_string(ticket); - } - /* Register ticket cleanup in case of fatal error. */ - if (!cleanup_registered) { - fatal_add_cleanup(krb4_cleanup_proc, NULL); - cleanup_registered = 1; - } - /* Try to create our ticket file. */ - if ((fd = mkstemp(ticket)) != -1) { - close(fd); - return 1; + xfree(authctxt->krb4_ticket_file); + authctxt->krb4_ticket_file = NULL; } - /* Ticket file exists - make sure user owns it (just passed ticket). */ - if (lstat(ticket, &st) != -1) { - if (st.st_mode == (S_IFREG | S_IRUSR | S_IWUSR) && - st.st_uid == uid) - return 1; - } - /* Failure - cancel cleanup function, leaving bad ticket for inspection. */ - log("WARNING: bad ticket file %s", ticket); - fatal_remove_cleanup(krb4_cleanup_proc, NULL); - cleanup_registered = 0; - xfree(ticket); - ticket = NULL; - - return 0; } int -auth_krb4(const char *server_user, KTEXT auth, char **client) +auth_krb4(Authctxt *authctxt, KTEXT auth, char **client) { AUTH_DAT adat = {0}; KTEXT_ST reply; + Key_schedule schedule; + struct sockaddr_in local, foreign; char instance[INST_SZ]; - int r, s; socklen_t slen; u_int cksum; - Key_schedule schedule; - struct sockaddr_in local, foreign; + int r, s; s = packet_get_connection_in(); @@ -238,9 +237,10 @@ instance[1] = 0; /* Get the encrypted request, challenge, and session key. */ - if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) { - packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]); - return 0; + if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, + 0, &adat, ""))) { + debug("Kerberos v4 krb_rd_req: %.100s", krb_err_txt[r]); + return (0); } des_key_sched((des_cblock *) adat.session, schedule); @@ -249,12 +249,12 @@ *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 %s to account %s", - *client, server_user); + if (kuserok(&adat, authctxt->user) != KSUCCESS) { + log("Kerberos v4 .klogin authorization failed for %s to " + "account %s", *client, authctxt->user); xfree(*client); - return 0; + *client = NULL; + return (0); } /* Increment the checksum, and return it encrypted with the session key. */ @@ -265,7 +265,7 @@ 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) %s", r, krb_err_txt[r]); + debug("Kerberos v4 mk_priv: (%d) %s", r, krb_err_txt[r]); reply.dat[0] = 0; reply.length = 0; } else @@ -278,89 +278,79 @@ packet_put_string((char *) reply.dat, reply.length); packet_send(); packet_write_wait(); - return 1; + return (1); } #endif /* KRB4 */ #ifdef AFS int -auth_krb4_tgt(struct passwd *pw, const char *string) +auth_krb4_tgt(Authctxt *authctxt, const char *string) { CREDENTIALS creds; + struct passwd *pw; + + if ((pw = authctxt->pw) == NULL) + goto failure; + + temporarily_use_uid(pw); - if (pw == NULL) - goto auth_kerberos_tgt_failure; 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; + log("Protocol error decoding Kerberos v4 TGT"); + goto failure; } if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */ strlcpy(creds.service, "krbtgt", sizeof creds.service); if (strcmp(creds.service, "krbtgt")) { - log("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", creds.pname, - creds.pinst[0] ? "." : "", creds.pinst, creds.realm, - pw->pw_name); - packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", + log("Kerberos v4 TGT (%s%s%s@%s) rejected for %s", creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm, pw->pw_name); - goto auth_kerberos_tgt_failure; + goto failure; } - if (!krb4_init(pw->pw_uid)) - goto auth_kerberos_tgt_failure; + if (!krb4_init(authctxt)) + goto failure; if (in_tkt(creds.pname, creds.pinst) != KSUCCESS) - goto auth_kerberos_tgt_failure; + goto failure; if (save_credentials(creds.service, creds.instance, creds.realm, - creds.session, creds.lifetime, creds.kvno, - &creds.ticket_st, creds.issue_date) != KSUCCESS) { - packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials"); - goto auth_kerberos_tgt_failure; + creds.session, creds.lifetime, creds.kvno, &creds.ticket_st, + creds.issue_date) != KSUCCESS) { + debug("Kerberos v4 TGT refused: couldn't save credentials"); + goto failure; } /* Successful authentication, passed all checks. */ chown(tkt_string(), pw->pw_uid, pw->pw_gid); - packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)", - creds.service, creds.instance, creds.realm, creds.pname, - creds.pinst[0] ? "." : "", creds.pinst, creds.realm); + debug("Kerberos v4 TGT accepted (%s%s%s@%s)", + creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm); memset(&creds, 0, sizeof(creds)); - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); - return 1; -auth_kerberos_tgt_failure: - krb4_cleanup_proc(NULL); + restore_uid(); + + return (1); + + failure: + krb4_cleanup_proc(authctxt); memset(&creds, 0, sizeof(creds)); - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - return 0; + restore_uid(); + + return (0); } int -auth_afs_token(struct passwd *pw, const char *token_string) +auth_afs_token(Authctxt *authctxt, const char *token_string) { CREDENTIALS creds; + struct passwd *pw; uid_t uid; - if (pw == NULL) { - /* XXX fake protocol error */ - packet_send_debug("Protocol error decoding AFS token"); - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - return 0; - } + if ((pw = authctxt->pw) == NULL) + return (0); + if (!radix_to_creds(token_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; + return (0); } if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */ strlcpy(creds.service, "afs", sizeof creds.service); @@ -371,22 +361,14 @@ uid = pw->pw_uid; if (kafs_settoken(creds.realm, uid, &creds)) { - log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm, - pw->pw_name); - packet_send_debug("AFS token (%s@%s) rejected for %s", creds.pname, - creds.realm, pw->pw_name); + log("AFS token (%s@%s) rejected for %s", + creds.pname, creds.realm, pw->pw_name); memset(&creds, 0, sizeof(creds)); - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - return 0; + return (0); } - packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service, - creds.realm, creds.pname, creds.realm); + debug("AFS token accepted (%s@%s)", creds.pname, creds.realm); memset(&creds, 0, sizeof(creds)); - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); - return 1; + + return (1); } #endif /* AFS */ Index: src/crypto/openssh/auth-krb5.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-krb5.c,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 auth-krb5.c --- src/crypto/openssh/auth-krb5.c 28 Sep 2001 01:33:33 -0000 1.2.2.4 +++ src/crypto/openssh/auth-krb5.c 30 Jun 2002 11:37:57 -0000 @@ -1,250 +1,409 @@ /* * Kerberos v5 authentication and ticket-passing routines. - * - * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.2.2.4 2001/09/28 01:33:33 green Exp $ + * + * $xFreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp$ + */ +/* + * Copyright (c) 2002 Daniel Kouril. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" +RCSID("$OpenBSD: auth-krb5.c,v 1.8 2002/03/19 10:49:35 markus Exp $"); + #include "ssh.h" #include "ssh1.h" #include "packet.h" #include "xmalloc.h" +#include "log.h" +#include "servconf.h" +#include "uidswap.h" +#include "auth.h" #ifdef KRB5 +#include +#ifndef HEIMDAL +#define krb5_get_err_text(context,code) error_message(code) +#endif /* !HEIMDAL */ + +extern ServerOptions options; + +static int +krb5_init(void *context) +{ + Authctxt *authctxt = (Authctxt *)context; + krb5_error_code problem; + static int cleanup_registered = 0; -krb5_context ssh_context = NULL; -krb5_auth_context auth_context; -krb5_ccache mem_ccache = NULL; /* Credential cache for acquired ticket */ - -/* Try krb5 authentication. server_user is passed for logging purposes only, - in auth is received ticket, in client is returned principal from the - ticket */ -int -auth_krb5(const char* server_user, krb5_data *auth, krb5_principal *client) + if (authctxt->krb5_ctx == NULL) { + problem = krb5_init_context(&authctxt->krb5_ctx); + if (problem) + return (problem); + krb5_init_ets(authctxt->krb5_ctx); + } + if (!cleanup_registered) { + fatal_add_cleanup(krb5_cleanup_proc, authctxt); + cleanup_registered = 1; + } + return (0); +} + +/* + * Try krb5 authentication. server_user is passed for logging purposes + * only, in auth is received ticket, in client is returned principal + * from the ticket + */ +int +auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) { krb5_error_code problem; - krb5_principal server = NULL; - krb5_principal tkt_client = NULL; + krb5_principal server; krb5_data reply; - krb5_ticket *ticket = NULL; - int fd; - int ret; - + krb5_ticket *ticket; + int fd, ret; + + ret = 0; + server = NULL; + ticket = NULL; reply.length = 0; - - problem = krb5_init(); - if (problem) - return 0; - - problem = krb5_auth_con_init(ssh_context, &auth_context); - if (problem) { - log("Kerberos v5 authentication failed: %.100s", - krb5_get_err_text(ssh_context, problem)); - return 0; - } - - fd = packet_get_connection_in(); - problem = krb5_auth_con_setaddrs_from_fd(ssh_context, auth_context, &fd); - if (problem) { - ret = 0; - goto err; - } - - problem = krb5_sname_to_principal(ssh_context, NULL, NULL , + problem = krb5_init(authctxt); + if (problem) + goto err; + + problem = krb5_auth_con_init(authctxt->krb5_ctx, + &authctxt->krb5_auth_ctx); + if (problem) + goto err; + + fd = packet_get_connection_in(); +#ifdef HEIMDAL + problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx, + authctxt->krb5_auth_ctx, &fd); +#else + problem = krb5_auth_con_genaddrs(authctxt->krb5_ctx, + authctxt->krb5_auth_ctx,fd, + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR | + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR); +#endif + if (problem) + goto err; + + problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL , KRB5_NT_SRV_HST, &server); - if (problem) { - ret = 0; - goto err; - } - - problem = krb5_rd_req(ssh_context, &auth_context, auth, server, NULL, - NULL, &ticket); - if (problem) { - ret = 0; - goto err; - } - - problem = krb5_copy_principal(ssh_context, ticket->client, &tkt_client); - if (problem) { - ret = 0; - goto err; - } - + if (problem) + goto err; + + problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx, + auth, server, NULL, NULL, &ticket); + if (problem) + goto err; + +#ifdef HEIMDAL + problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client, + &authctxt->krb5_user); +#else + problem = krb5_copy_principal(authctxt->krb5_ctx, + ticket->enc_part2->client, + &authctxt->krb5_user); +#endif + if (problem) + goto err; + /* if client wants mutual auth */ - problem = krb5_mk_rep(ssh_context, auth_context, &reply); - if (problem) { - ret = 0; - goto err; - } - - *client = tkt_client; - + problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, + &reply); + if (problem) + goto err; + + /* Check .k5login authorization now. */ + if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, + authctxt->pw->pw_name)) + goto err; + + if (client) + krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, + client); + packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE); packet_put_string((char *) reply.data, reply.length); packet_send(); packet_write_wait(); + ret = 1; - -err: + err: if (server) - krb5_free_principal(ssh_context, server); + krb5_free_principal(authctxt->krb5_ctx, server); if (ticket) - krb5_free_ticket(ssh_context, ticket); + krb5_free_ticket(authctxt->krb5_ctx, ticket); if (reply.length) - xfree(reply.data); - return ret; + xfree(reply.data); + + if (problem) { + if (authctxt->krb5_ctx != NULL) + debug("Kerberos v5 authentication failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + else + debug("Kerberos v5 authentication failed: %d", + problem); + } + + return (ret); } int -auth_krb5_tgt(char *server_user, krb5_data *tgt, krb5_principal tkt_client) +auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) +{ + krb5_error_code problem; + krb5_ccache ccache = NULL; + char *pname; + krb5_creds **creds; + + if (authctxt->pw == NULL || authctxt->krb5_user == NULL) + return (0); + + temporarily_use_uid(authctxt->pw); + +#ifdef HEIMDAL + problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache); +#else { - krb5_error_code problem; - krb5_ccache ccache = NULL; - - if (ssh_context == NULL) { - goto fail; - } - - problem = krb5_cc_gen_new(ssh_context, &krb5_mcc_ops, &ccache); - if (problem) { - goto fail; - } - - problem = krb5_cc_initialize(ssh_context, ccache, tkt_client); - if (problem) { - goto fail; - } - - problem = krb5_rd_cred2(ssh_context, auth_context, ccache, tgt); - if (problem) { - goto fail; - } - - mem_ccache = ccache; - ccache = NULL; - - /* - problem = krb5_cc_copy_cache(ssh_context, ccache, mem_ccache); - if (problem) { - mem_ccache = NULL; - goto fail; - } - - - problem = krb5_cc_destroy(ssh_context, ccache); - if (problem) - goto fail; - */ - -#if 0 - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); -#endif - return 1; - -fail: - if (ccache) - krb5_cc_destroy(ssh_context, ccache); -#if 0 - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); + char ccname[40]; + int tmpfd; + + snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); + + if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { + log("mkstemp(): %.100s", strerror(errno)); + problem = errno; + goto fail; + } + if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { + log("fchmod(): %.100s", strerror(errno)); + close(tmpfd); + problem = errno; + goto fail; + } + close(tmpfd); + problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &ccache); +} +#endif + if (problem) + goto fail; + + problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, + authctxt->krb5_user); + if (problem) + goto fail; + +#ifdef HEIMDAL + problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, + ccache, tgt); + if (problem) + goto fail; +#else + problem = krb5_rd_cred(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, + tgt, &creds, NULL); + if (problem) + goto fail; + problem = krb5_cc_store_cred(authctxt->krb5_ctx, ccache, *creds); + if (problem) + goto fail; #endif - return 0; + + authctxt->krb5_fwd_ccache = ccache; + ccache = NULL; + + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + + problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, + &pname); + if (problem) + goto fail; + + debug("Kerberos v5 TGT accepted (%s)", pname); + + restore_uid(); + + return (1); + + fail: + if (problem) + debug("Kerberos v5 TGT passing failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + if (ccache) + krb5_cc_destroy(authctxt->krb5_ctx, ccache); + + restore_uid(); + + return (0); } int -auth_krb5_password(struct passwd *pw, const char *password) +auth_krb5_password(Authctxt *authctxt, const char *password) { - krb5_error_code problem; - krb5_ccache ccache = NULL; - krb5_principal client = NULL; - int ret; - - problem = krb5_init(); - if (problem) - return 0; - - problem = krb5_parse_name(ssh_context, pw->pw_name, &client); - if (problem) { - ret = 0; - goto out; - } - - problem = krb5_cc_gen_new(ssh_context, &krb5_mcc_ops, &ccache); - if (problem) { - ret = 0; - goto out; - } - - problem = krb5_cc_initialize(ssh_context, ccache, client); - if (problem) { - ret = 0; - goto out; - } - - problem = krb5_verify_user(ssh_context, client, ccache, password, 1, NULL); - if (problem) { - ret = 0; - goto out; - } - -/* - problem = krb5_cc_copy_cache(ssh_context, ccache, mem_ccache); - if (problem) { - ret = 0; - mem_ccache = NULL; - goto out; - } - */ - mem_ccache = ccache; - ccache = NULL; - - ret = 1; -out: - if (client != NULL) - krb5_free_principal(ssh_context, client); - if (ccache != NULL) - krb5_cc_destroy(ssh_context, ccache); - return ret; +#ifndef HEIMDAL + krb5_creds creds; + krb5_principal server; + char ccname[40]; + int tmpfd; +#endif + krb5_error_code problem; + + if (authctxt->pw == NULL) + return (0); + + temporarily_use_uid(authctxt->pw); + + problem = krb5_init(authctxt); + if (problem) + goto out; + + problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, + &authctxt->krb5_user); + if (problem) + goto out; + +#ifdef HEIMDAL + problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, + &authctxt->krb5_fwd_ccache); + if (problem) + goto out; + + problem = krb5_cc_initialize(authctxt->krb5_ctx, + authctxt->krb5_fwd_ccache, authctxt->krb5_user); + if (problem) + goto out; + + restore_uid(); + problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, + authctxt->krb5_fwd_ccache, password, 1, NULL); + temporarily_use_uid(authctxt->pw); + + if (problem) + goto out; + +#else + problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, + authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL); + if (problem) + goto out; + + problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, + KRB5_NT_SRV_HST, &server); + if (problem) + goto out; + + restore_uid(); + problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, + NULL, NULL, NULL); + krb5_free_principal(authctxt->krb5_ctx, server); + temporarily_use_uid(authctxt->pw); + if (problem) + goto out; + + if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, + authctxt->pw->pw_name)) { + problem = -1; + goto out; + } + + snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); + + if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { + log("mkstemp(): %.100s", strerror(errno)); + problem = errno; + goto out; + } + + if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { + log("fchmod(): %.100s", strerror(errno)); + close(tmpfd); + problem = errno; + goto out; + } + close(tmpfd); + + problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache); + if (problem) + goto out; + + problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, + authctxt->krb5_user); + if (problem) + goto out; + + problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, + &creds); + if (problem) + goto out; +#endif + + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + + out: + restore_uid(); + + if (problem) { + if (authctxt->krb5_ctx != NULL && problem!=-1) + debug("Kerberos password authentication failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + else + debug("Kerberos password authentication failed: %d", + problem); + + krb5_cleanup_proc(authctxt); + + if (options.kerberos_or_local_passwd) + return (-1); + else + return (0); + } + return (1); } void -krb5_cleanup_proc(void *ignore) +krb5_cleanup_proc(void *context) { - extern krb5_principal tkt_client; - - debug("krb5_cleanup_proc() called"); - if (mem_ccache) - krb5_cc_destroy(ssh_context, mem_ccache); - if (tkt_client) - krb5_free_principal(ssh_context, tkt_client); - if (auth_context) - krb5_auth_con_free(ssh_context, auth_context); - if (ssh_context) - krb5_free_context(ssh_context); -} - -int -krb5_init(void) -{ - krb5_error_code problem; - static cleanup_registered = 0; - - if (ssh_context == NULL) { - problem = krb5_init_context(&ssh_context); - if (problem) - return problem; - krb5_init_ets(ssh_context); - } - - if (!cleanup_registered) { - fatal_add_cleanup(krb5_cleanup_proc, NULL); - cleanup_registered = 1; - } - return 0; + Authctxt *authctxt = (Authctxt *)context; + + debug("krb5_cleanup_proc called"); + if (authctxt->krb5_fwd_ccache) { + krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_fwd_ccache = NULL; + } + if (authctxt->krb5_user) { + krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); + authctxt->krb5_user = NULL; + } + if (authctxt->krb5_auth_ctx) { + krb5_auth_con_free(authctxt->krb5_ctx, + authctxt->krb5_auth_ctx); + authctxt->krb5_auth_ctx = NULL; + } + if (authctxt->krb5_ctx) { + krb5_free_context(authctxt->krb5_ctx); + authctxt->krb5_ctx = NULL; + } } - + #endif /* KRB5 */ Index: src/crypto/openssh/auth-options.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-options.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 auth-options.c --- src/crypto/openssh/auth-options.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/auth-options.c 30 Jun 2002 11:37:57 -0000 @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-options.c,v 1.16 2001/03/18 12:07:52 markus Exp $"); +RCSID("$OpenBSD: auth-options.c,v 1.24 2002/05/13 20:44:58 markus Exp $"); #include "packet.h" #include "xmalloc.h" @@ -20,6 +20,10 @@ #include "channels.h" #include "auth-options.h" #include "servconf.h" +#include "bufaux.h" +#include "misc.h" +#include "monitor_wrap.h" +#include "auth.h" /* Flags set authorized_keys flags */ int no_port_forwarding_flag = 0; @@ -53,6 +57,7 @@ forced_command = NULL; } channel_clear_permitted_opens(); + auth_debug_reset(); } /* @@ -74,28 +79,28 @@ while (*opts && *opts != ' ' && *opts != '\t') { cp = "no-port-forwarding"; if (strncasecmp(opts, cp, strlen(cp)) == 0) { - packet_send_debug("Port forwarding disabled."); + auth_debug_add("Port forwarding disabled."); no_port_forwarding_flag = 1; opts += strlen(cp); goto next_option; } cp = "no-agent-forwarding"; if (strncasecmp(opts, cp, strlen(cp)) == 0) { - packet_send_debug("Agent forwarding disabled."); + auth_debug_add("Agent forwarding disabled."); no_agent_forwarding_flag = 1; opts += strlen(cp); goto next_option; } cp = "no-X11-forwarding"; if (strncasecmp(opts, cp, strlen(cp)) == 0) { - packet_send_debug("X11 forwarding disabled."); + auth_debug_add("X11 forwarding disabled."); no_x11_forwarding_flag = 1; opts += strlen(cp); goto next_option; } cp = "no-pty"; if (strncasecmp(opts, cp, strlen(cp)) == 0) { - packet_send_debug("Pty allocation disabled."); + auth_debug_add("Pty allocation disabled."); no_pty_flag = 1; opts += strlen(cp); goto next_option; @@ -118,14 +123,14 @@ if (!*opts) { debug("%.100s, line %lu: missing end quote", file, linenum); - packet_send_debug("%.100s, line %lu: missing end quote", + auth_debug_add("%.100s, line %lu: missing end quote", file, linenum); xfree(forced_command); forced_command = NULL; goto bad_option; } forced_command[i] = 0; - packet_send_debug("Forced command: %.900s", forced_command); + auth_debug_add("Forced command: %.900s", forced_command); opts++; goto next_option; } @@ -150,13 +155,13 @@ if (!*opts) { debug("%.100s, line %lu: missing end quote", file, linenum); - packet_send_debug("%.100s, line %lu: missing end quote", + auth_debug_add("%.100s, line %lu: missing end quote", file, linenum); xfree(s); goto bad_option; } s[i] = 0; - packet_send_debug("Adding to environment: %.900s", s); + auth_debug_add("Adding to environment: %.900s", s); debug("Adding to environment: %.900s", s); opts++; new_envstring = xmalloc(sizeof(struct envstring)); @@ -167,10 +172,9 @@ } cp = "from=\""; if (strncasecmp(opts, cp, strlen(cp)) == 0) { - int mname, mip; const char *remote_ip = get_remote_ipaddr(); const char *remote_host = get_canonical_hostname( - options.reverse_mapping_check); + options.verify_reverse_mapping); char *patterns = xmalloc(strlen(opts) + 1); opts += strlen(cp); @@ -188,42 +192,34 @@ if (!*opts) { debug("%.100s, line %lu: missing end quote", file, linenum); - packet_send_debug("%.100s, line %lu: missing end quote", + auth_debug_add("%.100s, line %lu: missing end quote", file, linenum); xfree(patterns); goto bad_option; } patterns[i] = 0; opts++; - /* - * Deny access if we get a negative - * match for the hostname or the ip - * or if we get not match at all - */ - mname = match_hostname(remote_host, patterns, - strlen(patterns)); - mip = match_hostname(remote_ip, patterns, - strlen(patterns)); - xfree(patterns); - if (mname == -1 || mip == -1 || - (mname != 1 && mip != 1)) { + if (match_host_and_ip(remote_host, remote_ip, + patterns) != 1) { + xfree(patterns); log("Authentication tried for %.100s with " "correct key but not from a permitted " "host (host=%.200s, ip=%.200s).", pw->pw_name, remote_host, remote_ip); - packet_send_debug("Your host '%.200s' is not " + auth_debug_add("Your host '%.200s' is not " "permitted to use this key for login.", remote_host); /* deny access */ return 0; } + xfree(patterns); /* Host name matches. */ goto next_option; } cp = "permitopen=\""; if (strncasecmp(opts, cp, strlen(cp)) == 0) { + char host[256], sport[6]; u_short port; - char *c, *ep; char *patterns = xmalloc(strlen(opts) + 1); opts += strlen(cp); @@ -241,35 +237,32 @@ if (!*opts) { debug("%.100s, line %lu: missing end quote", file, linenum); - packet_send_debug("%.100s, line %lu: missing end quote", + auth_debug_add("%.100s, line %lu: missing end quote", file, linenum); xfree(patterns); goto bad_option; } patterns[i] = 0; opts++; - c = strchr(patterns, ':'); - if (c == NULL) { - debug("%.100s, line %lu: permitopen: missing colon <%.100s>", - file, linenum, patterns); - packet_send_debug("%.100s, line %lu: missing colon", - file, linenum); + if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && + sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { + debug("%.100s, line %lu: Bad permitopen specification " + "<%.100s>", file, linenum, patterns); + auth_debug_add("%.100s, line %lu: " + "Bad permitopen specification", file, linenum); xfree(patterns); goto bad_option; } - *c = 0; - c++; - port = strtol(c, &ep, 0); - if (c == ep) { - debug("%.100s, line %lu: permitopen: missing port <%.100s>", - file, linenum, patterns); - packet_send_debug("%.100s, line %lu: missing port", - file, linenum); + if ((port = a2port(sport)) == 0) { + debug("%.100s, line %lu: Bad permitopen port <%.100s>", + file, linenum, sport); + auth_debug_add("%.100s, line %lu: " + "Bad permitopen port", file, linenum); xfree(patterns); goto bad_option; } if (options.allow_tcp_forwarding) - channel_add_permitted_opens(patterns, port); + channel_add_permitted_opens(host, port); xfree(patterns); goto next_option; } @@ -287,14 +280,22 @@ opts++; /* Process the next option. */ } + + if (!use_privsep) + auth_debug_send(); + /* grant access */ return 1; bad_option: log("Bad options in %.100s file, line %lu: %.50s", file, linenum, opts); - packet_send_debug("Bad options in %.100s file, line %lu: %.50s", + auth_debug_add("Bad options in %.100s file, line %lu: %.50s", file, linenum, opts); + + if (!use_privsep) + auth_debug_send(); + /* deny access */ return 0; } Index: src/crypto/openssh/auth-options.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-options.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 auth-options.h --- src/crypto/openssh/auth-options.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/auth-options.h 30 Jun 2002 11:37:57 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: auth-options.h,v 1.11 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* $OpenBSD: auth-options.h,v 1.8 2001/01/21 19:05:42 markus Exp $ */ - #ifndef AUTH_OPTIONS_H #define AUTH_OPTIONS_H @@ -30,15 +30,7 @@ extern char *forced_command; extern struct envstring *custom_environment; -/* - * return 1 if access is granted, 0 if not. - * side effect: sets key option flags - */ -int -auth_parse_options(struct passwd *pw, char *options, char *file, - u_long linenum); - -/* reset options flags */ +int auth_parse_options(struct passwd *, char *, char *, u_long); void auth_clear_options(void); #endif Index: src/crypto/openssh/auth-pam.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-pam.c,v retrieving revision 1.2.2.2 diff -u -u -r1.2.2.2 auth-pam.c --- src/crypto/openssh/auth-pam.c 28 Sep 2001 01:33:33 -0000 1.2.2.2 +++ src/crypto/openssh/auth-pam.c 30 Jun 2002 11:37:57 -0000 @@ -25,41 +25,36 @@ #include "includes.h" #ifdef USE_PAM -#include #include "ssh.h" #include "xmalloc.h" #include "log.h" +#include "auth.h" +#include "auth-pam.h" #include "servconf.h" -#include "readpass.h" #include "canohost.h" +#include "readpass.h" -RCSID("$FreeBSD: src/crypto/openssh/auth-pam.c,v 1.2.2.2 2001/09/28 01:33:33 green Exp $"); +extern char *__progname; + +RCSID("$Id$"); #define NEW_AUTHTOK_MSG \ "Warning: Your password has expired, please change it now" -#define SSHD_PAM_SERVICE "sshd" -#define PAM_STRERROR(a, b) pam_strerror((a), (b)) - -/* Callbacks */ static int do_pam_conversation(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr); -void do_pam_cleanup_proc(void *context); -void pam_msg_cat(const char *msg); + struct pam_response **resp, void *appdata_ptr); /* module-local variables */ static struct pam_conv conv = { do_pam_conversation, NULL }; -static pam_handle_t *pamh = NULL; -static const char *pampasswd = NULL; -static char *pam_msg = NULL; -extern ServerOptions options; +static char *__pam_msg = NULL; +static pam_handle_t *__pamh = NULL; +static const char *__pampasswd = NULL; /* states for do_pam_conversation() */ -typedef enum { INITIAL_LOGIN, OTHER } pamstates; -static pamstates pamstate = INITIAL_LOGIN; +enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN; /* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */ static int password_change_required = 0; /* remember whether the last pam_authenticate() succeeded or not */ @@ -69,13 +64,19 @@ static int session_opened = 0; static int creds_set = 0; -/* - * accessor which allows us to switch conversation structs according to - * the authentication method being used - */ +/* accessor which allows us to switch conversation structs according to + * the authentication method being used */ void do_pam_set_conv(struct pam_conv *conv) { - pam_set_item(pamh, PAM_CONV, conv); + pam_set_item(__pamh, PAM_CONV, conv); +} + +/* start an authentication run */ +int do_pam_authenticate(int flags) +{ + int retval = pam_authenticate(__pamh, flags); + was_authenticated = (retval == PAM_SUCCESS); + return retval; } /* @@ -84,10 +85,10 @@ * * INITIAL_LOGIN mode simply feeds the password from the client into * PAM in response to PAM_PROMPT_ECHO_OFF, and collects output - * messages with pam_msg_cat(). This is used during initial + * messages with into __pam_msg. This is used during initial * authentication to bypass the normal PAM password prompt. * - * OTHER mode handles PAM_PROMPT_ECHO_OFF with read_passphrase(prompt, 1) + * OTHER mode handles PAM_PROMPT_ECHO_OFF with read_passphrase() * and outputs messages to stderr. This mode is used if pam_chauthtok() * is called to update expired passwords. */ @@ -101,43 +102,31 @@ /* PAM will free this later */ reply = malloc(num_msg * sizeof(*reply)); if (reply == NULL) - return PAM_CONV_ERR; + return PAM_CONV_ERR; for (count = 0; count < num_msg; count++) { - switch ((*msg)[count].msg_style) { + if (pamstate == INITIAL_LOGIN) { + /* + * We can't use stdio yet, queue messages for + * printing later + */ + switch(PAM_MSG_MEMBER(msg, count, msg_style)) { case PAM_PROMPT_ECHO_ON: - if (pamstate == INITIAL_LOGIN) { + free(reply); + return PAM_CONV_ERR; + case PAM_PROMPT_ECHO_OFF: + if (__pampasswd == NULL) { free(reply); return PAM_CONV_ERR; - } else { - fputs((*msg)[count].msg, stderr); - fgets(buf, sizeof(buf), stdin); - reply[count].resp = xstrdup(buf); - reply[count].resp_retcode = PAM_SUCCESS; - break; - } - case PAM_PROMPT_ECHO_OFF: - if (pamstate == INITIAL_LOGIN) { - if (pampasswd == NULL) { - free(reply); - return PAM_CONV_ERR; - } - reply[count].resp = xstrdup(pampasswd); - } else { - reply[count].resp = - xstrdup(read_passphrase((*msg)[count].msg, 1)); } + reply[count].resp = xstrdup(__pampasswd); reply[count].resp_retcode = PAM_SUCCESS; break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: if ((*msg)[count].msg != NULL) { - if (pamstate == INITIAL_LOGIN) - pam_msg_cat((*msg)[count].msg); - else { - fputs((*msg)[count].msg, stderr); - fputs("\n", stderr); - } + message_cat(&__pam_msg, + PAM_MSG_MEMBER(msg, count, msg)); } reply[count].resp = xstrdup(""); reply[count].resp_retcode = PAM_SUCCESS; @@ -145,6 +134,36 @@ default: free(reply); return PAM_CONV_ERR; + } + } else { + /* + * stdio is connected, so interact directly + */ + switch(PAM_MSG_MEMBER(msg, count, msg_style)) { + case PAM_PROMPT_ECHO_ON: + fputs(PAM_MSG_MEMBER(msg, count, msg), stderr); + fgets(buf, sizeof(buf), stdin); + reply[count].resp = xstrdup(buf); + reply[count].resp_retcode = PAM_SUCCESS; + break; + case PAM_PROMPT_ECHO_OFF: + reply[count].resp = + read_passphrase(PAM_MSG_MEMBER(msg, count, + msg), RP_ALLOW_STDIN); + reply[count].resp_retcode = PAM_SUCCESS; + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + if ((*msg)[count].msg != NULL) + fprintf(stderr, "%s\n", + PAM_MSG_MEMBER(msg, count, msg)); + reply[count].resp = xstrdup(""); + reply[count].resp_retcode = PAM_SUCCESS; + break; + default: + free(reply); + return PAM_CONV_ERR; + } } } @@ -156,61 +175,60 @@ /* Called at exit to cleanly shutdown PAM */ void do_pam_cleanup_proc(void *context) { - int pam_retval; + int pam_retval = PAM_SUCCESS; - if (pamh != NULL && session_opened) { - pam_retval = pam_close_session(pamh, 0); - if (pam_retval != PAM_SUCCESS) { - log("Cannot close PAM session[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + if (__pamh && session_opened) { + pam_retval = pam_close_session(__pamh, 0); + if (pam_retval != PAM_SUCCESS) + log("Cannot close PAM session[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); } - if (pamh != NULL && creds_set) { - pam_retval = pam_setcred(pamh, PAM_DELETE_CRED); - if (pam_retval != PAM_SUCCESS) { + if (__pamh && creds_set) { + pam_retval = pam_setcred(__pamh, PAM_DELETE_CRED); + if (pam_retval != PAM_SUCCESS) debug("Cannot delete credentials[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + pam_retval, PAM_STRERROR(__pamh, pam_retval)); } - if (pamh != NULL) { - pam_retval = pam_end(pamh, pam_retval); - if (pam_retval != PAM_SUCCESS) { - log("Cannot release PAM authentication[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + if (__pamh) { + pam_retval = pam_end(__pamh, pam_retval); + if (pam_retval != PAM_SUCCESS) + log("Cannot release PAM authentication[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); } } /* Attempt password authentation using PAM */ int auth_pam_password(Authctxt *authctxt, const char *password) { - struct passwd *pw = authctxt->pw; + extern ServerOptions options; int pam_retval; + struct passwd *pw = authctxt->pw; do_pam_set_conv(&conv); /* deny if no user. */ if (pw == NULL) return 0; - if (pw->pw_uid == 0 && options.permit_root_login == 2) + if (pw->pw_uid == 0 && options.permit_root_login == PERMIT_NO_PASSWD) return 0; if (*password == '\0' && options.permit_empty_passwd == 0) return 0; - pampasswd = password; - + __pampasswd = password; + pamstate = INITIAL_LOGIN; - pam_retval = pam_authenticate(pamh, 0); - was_authenticated = (pam_retval == PAM_SUCCESS); + pam_retval = do_pam_authenticate( + options.permit_empty_passwd == 0 ? PAM_DISALLOW_NULL_AUTHTOK : 0); if (pam_retval == PAM_SUCCESS) { - debug("PAM Password authentication accepted for user \"%.100s\"", - pw->pw_name); + debug("PAM Password authentication accepted for " + "user \"%.100s\"", pw->pw_name); return 1; } else { - debug("PAM Password authentication for \"%.100s\" failed[%d]: %s", - pw->pw_name, pam_retval, PAM_STRERROR(pamh, pam_retval)); + debug("PAM Password authentication for \"%.100s\" " + "failed[%d]: %s", pw->pw_name, pam_retval, + PAM_STRERROR(__pamh, pam_retval)); return 0; } } @@ -221,41 +239,35 @@ int pam_retval; do_pam_set_conv(&conv); - - debug("PAM setting rhost to \"%.200s\"", - get_canonical_hostname(options.reverse_mapping_check)); - pam_retval = pam_set_item(pamh, PAM_RHOST, - get_canonical_hostname(options.reverse_mapping_check)); - if (pam_retval != PAM_SUCCESS) { - fatal("PAM set rhost failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } - if (remote_user != NULL) { + if (remote_user) { debug("PAM setting ruser to \"%.200s\"", remote_user); - pam_retval = pam_set_item(pamh, PAM_RUSER, remote_user); - if (pam_retval != PAM_SUCCESS) { - fatal("PAM set ruser failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + pam_retval = pam_set_item(__pamh, PAM_RUSER, remote_user); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set ruser failed[%d]: %.200s", pam_retval, + PAM_STRERROR(__pamh, pam_retval)); } - pam_retval = pam_acct_mgmt(pamh, 0); + pam_retval = pam_acct_mgmt(__pamh, 0); + debug2("pam_acct_mgmt() = %d", pam_retval); switch (pam_retval) { case PAM_SUCCESS: /* This is what we want */ break; +#if 0 case PAM_NEW_AUTHTOK_REQD: - pam_msg_cat(NEW_AUTHTOK_MSG); + message_cat(&__pam_msg, NEW_AUTHTOK_MSG); /* flag that password change is necessary */ password_change_required = 1; break; +#endif default: - log("PAM rejected by account configuration[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); + log("PAM rejected by account configuration[%d]: " + "%.200s", pam_retval, PAM_STRERROR(__pamh, + pam_retval)); return(0); } - + return(1); } @@ -268,50 +280,51 @@ if (ttyname != NULL) { debug("PAM setting tty to \"%.200s\"", ttyname); - pam_retval = pam_set_item(pamh, PAM_TTY, ttyname); - if (pam_retval != PAM_SUCCESS) { - fatal("PAM set tty failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + pam_retval = pam_set_item(__pamh, PAM_TTY, ttyname); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set tty failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); } - debug("do_pam_session: euid %u, uid %u", geteuid(), getuid()); - pam_retval = pam_open_session(pamh, 0); - if (pam_retval != PAM_SUCCESS) { - fatal("PAM session setup failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + pam_retval = pam_open_session(__pamh, 0); + if (pam_retval != PAM_SUCCESS) + fatal("PAM session setup failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); session_opened = 1; } -/* Set PAM credentials */ -void do_pam_setcred(void) +/* Set PAM credentials */ +void do_pam_setcred(int init) { int pam_retval; + if (__pamh == NULL) + return; + do_pam_set_conv(&conv); - + debug("PAM establishing creds"); - pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED); + pam_retval = pam_setcred(__pamh, + init ? PAM_ESTABLISH_CRED : PAM_REINITIALIZE_CRED); if (pam_retval != PAM_SUCCESS) { if (was_authenticated) fatal("PAM setcred failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); + pam_retval, PAM_STRERROR(__pamh, pam_retval)); else debug("PAM setcred failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); + pam_retval, PAM_STRERROR(__pamh, pam_retval)); } else creds_set = 1; } /* accessor function for file scope static variable */ -int pam_password_change_required(void) +int is_pam_password_change_required(void) { return password_change_required; } -/* +/* * Have user change authentication token if pam_acct_mgmt() indicated * it was expired. This needs to be called after an interactive * session is established and the user's pty is connected to @@ -325,16 +338,10 @@ if (password_change_required) { pamstate = OTHER; - /* - * XXX: should we really loop forever? - */ - do { - pam_retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); - if (pam_retval != PAM_SUCCESS) { - log("PAM pam_chauthtok failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } - } while (pam_retval != PAM_SUCCESS); + pam_retval = pam_chauthtok(__pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + if (pam_retval != PAM_SUCCESS) + fatal("PAM pam_chauthtok failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); } } @@ -346,32 +353,40 @@ } /* Start PAM authentication for specified account */ -void start_pam(struct passwd *pw) +void start_pam(const char *user) { int pam_retval; + extern ServerOptions options; + extern u_int utmp_len; + const char *rhost; - debug("Starting up PAM with username \"%.200s\"", pw->pw_name); + debug("Starting up PAM with username \"%.200s\"", user); - pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, &pamh); + pam_retval = pam_start(SSHD_PAM_SERVICE, user, &conv, &__pamh); - if (pam_retval != PAM_SUCCESS) { - fatal("PAM initialisation failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + if (pam_retval != PAM_SUCCESS) + fatal("PAM initialisation failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); + rhost = get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping); + debug("PAM setting rhost to \"%.200s\"", rhost); + + pam_retval = pam_set_item(__pamh, PAM_RHOST, rhost); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set rhost failed[%d]: %.200s", pam_retval, + PAM_STRERROR(__pamh, pam_retval)); #ifdef PAM_TTY_KLUDGE /* * Some PAM modules (e.g. pam_time) require a TTY to operate, - * and will fail in various stupid ways if they don't get one. + * and will fail in various stupid ways if they don't get one. * sshd doesn't set the tty until too late in the auth process and may * not even need one (for tty-less connections) - * Kludge: Set a fake PAM_TTY + * Kludge: Set a fake PAM_TTY */ - pam_retval = pam_set_item(pamh, PAM_TTY, "ssh"); - if (pam_retval != PAM_SUCCESS) { - fatal("PAM set tty failed[%d]: %.200s", - pam_retval, PAM_STRERROR(pamh, pam_retval)); - } + pam_retval = pam_set_item(__pamh, PAM_TTY, "NODEVssh"); + if (pam_retval != PAM_SUCCESS) + fatal("PAM set tty failed[%d]: %.200s", + pam_retval, PAM_STRERROR(__pamh, pam_retval)); #endif /* PAM_TTY_KLUDGE */ fatal_add_cleanup(&do_pam_cleanup_proc, NULL); @@ -381,7 +396,7 @@ char **fetch_pam_environment(void) { #ifdef HAVE_PAM_GETENVLIST - return(pam_getenvlist(pamh)); + return(pam_getenvlist(__pamh)); #else /* HAVE_PAM_GETENVLIST */ return(NULL); #endif /* HAVE_PAM_GETENVLIST */ @@ -391,428 +406,29 @@ /* or account checking to stderr */ void print_pam_messages(void) { - if (pam_msg != NULL) - fputs(pam_msg, stderr); + if (__pam_msg != NULL) + fputs(__pam_msg, stderr); } -/* Append a message to the PAM message buffer */ -void pam_msg_cat(const char *msg) +/* Append a message to buffer */ +void message_cat(char **p, const char *a) { - char *p; - size_t new_msg_len; - size_t pam_msg_len; - - new_msg_len = strlen(msg); - - if (pam_msg) { - pam_msg_len = strlen(pam_msg); - pam_msg = xrealloc(pam_msg, new_msg_len + pam_msg_len + 2); - p = pam_msg + pam_msg_len; - } else { - pam_msg = p = xmalloc(new_msg_len + 2); - } - - memcpy(p, msg, new_msg_len); - p[new_msg_len] = '\n'; - p[new_msg_len + 1] = '\0'; -} - -struct inverted_pam_userdata { - /* - * Pipe for telling whether we are doing conversation or sending - * authentication results. - */ - int statefd[2]; - int challengefd[2]; - int responsefd[2]; + char *cp; + size_t new_len; - /* Whether we have sent off our challenge */ - int state; -}; + new_len = strlen(a); -#define STATE_CONV 1 -#define STATE_AUTH_OK 2 -#define STATE_AUTH_FAIL 3 - -int -ssh_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, - void *userdata) { - int i; - FILE *reader; - char buf[1024]; - struct pam_response *reply = NULL; - char state_to_write = STATE_CONV; /* One char to write */ - struct inverted_pam_userdata *ud = userdata; - char *response = NULL; - - /* The stdio functions are more convenient for the read half */ - reader = fdopen(ud->responsefd[0], "rb"); - if (reader == NULL) - goto protocol_failure; + if (*p) { + size_t len = strlen(*p); - reply = malloc(num_msg * sizeof(struct pam_response)); - if (reply == NULL) - return PAM_CONV_ERR; - - if (write(ud->statefd[1], &state_to_write, 1) != 1) - goto protocol_failure; - - /* - * Re-package our data and send it off to our better half (the actual SSH - * process) - */ - if (write(ud->challengefd[1], buf, - sprintf(buf, "%d\n", num_msg)) == -1) - goto protocol_failure; - for (i = 0; i < num_msg; i++) { - if (write(ud->challengefd[1], buf, - sprintf(buf, "%d\n", msg[i]->msg_style)) == -1) - goto protocol_failure; - if (write(ud->challengefd[1], buf, - sprintf(buf, "%d\n", strlen(msg[i]->msg))) == -1) - goto protocol_failure; - if (write(ud->challengefd[1], msg[i]->msg, - strlen(msg[i]->msg)) == -1) - goto protocol_failure; - } - /* - * Read back responses. These may not be as nice as we want, as the SSH - * protocol isn't exactly a perfect fit with PAM. - */ - - for (i = 0; i < num_msg; i++) { - char buf[1024]; - char *endptr; - size_t len; /* Length of the response */ - - switch (msg[i]->msg_style) { - case PAM_PROMPT_ECHO_OFF: - case PAM_PROMPT_ECHO_ON: - if (fgets(buf, sizeof(buf), reader) == NULL) - goto protocol_failure; - len = (size_t)strtoul(buf, &endptr, 10); - /* The length is supposed to stand on a line by itself */ - if (endptr == NULL || *endptr != '\n') - goto protocol_failure; - response = malloc(len+1); - if (response == NULL) - goto protocol_failure; - if (fread(response, len, 1, reader) != 1) - goto protocol_failure; - response[len] = '\0'; - reply[i].resp = response; - response = NULL; - break; - default: - reply[i].resp = NULL; - break; - } - } - *resp = reply; - return PAM_SUCCESS; - protocol_failure: - free(reply); - return PAM_CONV_ERR; -} - -void -ipam_free_cookie(struct inverted_pam_cookie *cookie) { - struct inverted_pam_userdata *ud; - int i; - - if (cookie == NULL) - return; - ud = cookie->userdata; - cookie->userdata = NULL; - /* Free userdata if allocated */ - if (ud) { - /* Close any opened file descriptors */ - if (ud->statefd[0] != -1) - close(ud->statefd[0]); - if (ud->statefd[1] != -1) - close(ud->statefd[1]); - if (ud->challengefd[0] != -1) - close(ud->challengefd[0]); - if (ud->challengefd[1] != -1) - close(ud->challengefd[1]); - if (ud->responsefd[0] != -1) - close(ud->responsefd[0]); - if (ud->responsefd[1] != -1) - close(ud->responsefd[1]); - free(ud); - ud = NULL; - } - /* Now free the normal cookie */ - if (cookie->pid != 0 && cookie->pid != -1) { - int status; - - /* XXX Use different signal? */ - kill(cookie->pid, SIGKILL); - waitpid(cookie->pid, &status, 0); - } - for (i = 0; i < cookie->num_msg; i++) { - if (cookie->resp && cookie->resp[i]) { - free(cookie->resp[i]->resp); - free(cookie->resp[i]); - } - if (cookie->msg && cookie->msg[i]) { - free((void *)cookie->msg[i]->msg); - free(cookie->msg[i]); - } - } - free(cookie->msg); - free(cookie->resp); - free(cookie); -} - -/* - * Do first half of PAM authentication - this comes to the point where - * you get a message to send to the user. - */ -struct inverted_pam_cookie * -ipam_start_auth(const char *service, const char *username) { - struct inverted_pam_cookie *cookie; - struct inverted_pam_userdata *ud; - static struct pam_conv conv = { - ssh_conv, - NULL - }; - - cookie = malloc(sizeof(*cookie)); - if (cookie == NULL) - return NULL; - cookie->state = 0; - /* Set up the cookie so ipam_freecookie can be used on it */ - cookie->num_msg = 0; - cookie->msg = NULL; - cookie->resp = NULL; - cookie->pid = -1; - - ud = calloc(sizeof(*ud), 1); - if (ud == NULL) { - free(cookie); - return NULL; - } - cookie->userdata = ud; - ud->statefd[0] = ud->statefd[1] = -1; - ud->challengefd[0] = ud->challengefd[1] = -1; - ud->responsefd[0] = ud->responsefd[1] = -1; - - if (pipe(ud->statefd) != 0) { - ud->statefd[0] = ud->statefd[1] = -1; - ipam_free_cookie(cookie); - return NULL; - } - if (pipe(ud->challengefd) != 0) { - ud->challengefd[0] = ud->challengefd[1] = -1; - ipam_free_cookie(cookie); - return NULL; - } - if (pipe(ud->responsefd) != 0) { - ud->responsefd[0] = ud->responsefd[1] = -1; - ipam_free_cookie(cookie); - return NULL; - } - cookie->pid = fork(); - if (cookie->pid == -1) { - ipam_free_cookie(cookie); - return NULL; - } else if (cookie->pid != 0) { - int num_msgs; /* Number of messages from PAM */ - char *endptr; - char buf[1024]; - FILE *reader; - size_t num_msg; - int i; - char state; /* Which state did the connection just enter? */ - - /* We are the parent - wait for a call to the communications - function to turn up, or the challenge to be finished */ - if (read(ud->statefd[0], &state, 1) != 1) { - ipam_free_cookie(cookie); - return NULL; - } - cookie->state = state; - switch (state) { - case STATE_CONV: - /* We are running the conversation function */ - /* The stdio functions are more convenient for read */ - reader = fdopen(ud->challengefd[0], "r"); - if (reader == NULL) { - ipam_free_cookie(cookie); - return NULL; - } - if (fgets(buf, 4, reader) == NULL) { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - num_msg = (size_t)strtoul(buf, &endptr, 10); - /* The length is supposed to stand on a line by itself */ - if (endptr == NULL || *endptr != '\n') { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - cookie->msg = - malloc(sizeof(struct pam_message *) * num_msg); - cookie->resp = - malloc(sizeof(struct pam_response *) * num_msg); - if (cookie->msg == NULL || cookie->resp == NULL) { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - for (i = 0; i < num_msg; i++) { - cookie->msg[i] = - malloc(sizeof(struct pam_message)); - cookie->resp[i] = - malloc(sizeof(struct pam_response)); - if (cookie->msg[i] == NULL || - cookie->resp[i] == NULL) { - for (;;) { - free(cookie->msg[i]); - free(cookie->resp[i]); - if (i == 0) - break; - i--; - } - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - cookie->msg[i]->msg = NULL; - cookie->resp[i]->resp = NULL; - cookie->resp[i]->resp_retcode = 0; - } - /* Set up so the above will be freed on failure */ - cookie->num_msg = num_msg; - /* - * We have a an allocated response and message for - * each of the entries in the PAM structure - transfer - * the data sent to the conversation function over. - */ - for (i = 0; i < num_msg; i++) { - size_t len; - - if (fgets(buf, sizeof(buf), reader) == NULL) { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - cookie->msg[i]->msg_style = - (size_t)strtoul(buf, &endptr, 10); - if (endptr == NULL || *endptr != '\n') { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - if (fgets(buf, sizeof(buf), reader) == NULL) { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - len = (size_t)strtoul(buf, &endptr, 10); - if (endptr == NULL || *endptr != '\n') { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - cookie->msg[i]->msg = malloc(len + 1); - if (cookie->msg[i]->msg == NULL) { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - if (fread((char *)cookie->msg[i]->msg, len, 1, reader) != - 1) { - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - *(char *)&(cookie->msg[i]->msg[len]) = '\0'; - } - break; - case STATE_AUTH_OK: - case STATE_AUTH_FAIL: - break; - default: - /* Internal failure, somehow */ - fclose(reader); - ipam_free_cookie(cookie); - return NULL; - } - return cookie; - } else { - /* We are the child */ - pam_handle_t *pamh=NULL; - int retval; - char state; - - conv.appdata_ptr = ud; - retval = pam_start(service, username, &conv, &pamh); - /* Is user really user? */ - if (retval == PAM_SUCCESS) - retval = pam_authenticate(pamh, 0); - /* permitted access? */ - if (retval == PAM_SUCCESS) - retval = pam_acct_mgmt(pamh, 0); - /* This is where we have been authorized or not. */ - - /* Be conservative - flag as auth failure if we can't close */ - /* - * XXX This is based on example code from Linux-PAM - - * but can it really be correct to pam_end if - * pam_start failed? - */ - if (pam_end(pamh, retval) != PAM_SUCCESS) - retval = PAM_AUTH_ERR; - - /* Message to parent */ - state = retval == PAM_SUCCESS ? STATE_AUTH_OK : STATE_AUTH_FAIL; - if (write(ud->statefd[1], &state, 1) != 1) { - _exit(1); - } - /* FDs will be closed, so further communication will stop */ - _exit(0); - } -} - -/* - * Do second half of PAM authentication - cookie should now be filled - * in with the response to the challenge. - */ + *p = xrealloc(*p, new_len + len + 2); + cp = *p + len; + } else + *p = cp = xmalloc(new_len + 2); -int -ipam_complete_auth(struct inverted_pam_cookie *cookie) { - int i; - char buf[1024]; - struct inverted_pam_userdata *ud = cookie->userdata; - char state; - - /* Send over our responses */ - for (i = 0; i < cookie->num_msg; i++) { - if (cookie->msg[i]->msg_style != PAM_PROMPT_ECHO_ON && - cookie->msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) - continue; - if (write(ud->responsefd[1], buf, - sprintf(buf, "%d\n", strlen(cookie->resp[i]->resp))) == -1) { - ipam_free_cookie(cookie); - return 0; - } - if (write(ud->responsefd[1], cookie->resp[i]->resp, - strlen(cookie->resp[i]->resp)) == -1) { - ipam_free_cookie(cookie); - return 0; - } - } - /* Find out what state we are changing to */ - if (read(ud->statefd[0], &state, 1) != 1) { - ipam_free_cookie(cookie); - return 0; - } - - return state == STATE_AUTH_OK ? 1 : 0; + memcpy(cp, a, new_len); + cp[new_len] = '\n'; + cp[new_len + 1] = '\0'; } #endif /* USE_PAM */ Index: src/crypto/openssh/auth-pam.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-pam.h,v retrieving revision 1.2.2.2 diff -u -u -r1.2.2.2 auth-pam.h --- src/crypto/openssh/auth-pam.h 28 Sep 2001 01:33:33 -0000 1.2.2.2 +++ src/crypto/openssh/auth-pam.h 30 Jun 2002 11:37:57 -0000 @@ -1,39 +1,22 @@ -/* - * OpenSSH PAM authentication support. - * - * $FreeBSD: src/crypto/openssh/auth-pam.h,v 1.2.2.2 2001/09/28 01:33:33 green Exp $ - */ -#ifndef AUTH_PAM_H -#define AUTH_PAM_H +/* $Id$ */ + #include "includes.h" #ifdef USE_PAM -#include "auth.h" #include /* For struct passwd */ -void start_pam(struct passwd *pw); +void start_pam(const char *user); void finish_pam(void); int auth_pam_password(Authctxt *authctxt, const char *password); char **fetch_pam_environment(void); +int do_pam_authenticate(int flags); int do_pam_account(char *username, char *remote_user); void do_pam_session(char *username, const char *ttyname); -void do_pam_setcred(void); +void do_pam_setcred(int init); void print_pam_messages(void); -int pam_password_change_required(void); +int is_pam_password_change_required(void); void do_pam_chauthtok(void); - -struct inverted_pam_cookie { - int state; /* Which state have we reached? */ - pid_t pid; /* PID of child process */ - - /* Only valid in state STATE_CONV */ - int num_msg; /* Number of messages */ - struct pam_message **msg; /* Message structures */ - struct pam_response **resp; /* Response structures */ - struct inverted_pam_userdata *userdata; -}; -void ipam_free_cookie(struct inverted_pam_cookie *cookie); -struct inverted_pam_cookie *ipam_start_auth(const char *, const char *); +void do_pam_set_conv(struct pam_conv *); +void message_cat(char **p, const char *a); #endif /* USE_PAM */ -#endif /* AUTH_PAM_H */ Index: src/crypto/openssh/auth-passwd.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-passwd.c,v retrieving revision 1.2.2.5 diff -u -u -r1.2.2.5 auth-passwd.c --- src/crypto/openssh/auth-passwd.c 28 Sep 2001 01:33:33 -0000 1.2.2.5 +++ src/crypto/openssh/auth-passwd.c 30 Jun 2002 11:37:57 -0000 @@ -36,15 +36,49 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-passwd.c,v 1.22 2001/03/20 18:57:04 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth-passwd.c,v 1.2.2.5 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $"); #include "packet.h" -#include "xmalloc.h" #include "log.h" #include "servconf.h" #include "auth.h" +#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA) +/* Don't need any of these headers for the PAM or SIA cases */ +# ifdef HAVE_CRYPT_H +# include +# endif +# ifdef WITH_AIXAUTHENTICATE +# include +# endif +# ifdef __hpux +# include +# include +# endif +# ifdef HAVE_SECUREWARE +# include +# include +# include +# endif /* HAVE_SECUREWARE */ +# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) +# include +# endif +# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) +# include +# include +# include +# endif +# if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) +# include "md5crypt.h" +# endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */ + +# ifdef HAVE_CYGWIN +# undef ERROR +# include +# include +# define is_winnt (GetVersion() < 0x80000000) +# endif +#endif /* !USE_PAM && !HAVE_OSF_SIA */ extern ServerOptions options; @@ -55,47 +89,135 @@ int auth_password(Authctxt *authctxt, const char *password) { +#if defined(USE_PAM) + if (*password == '\0' && options.permit_empty_passwd == 0) + return 0; + return auth_pam_password(authctxt, password); +#elif defined(HAVE_OSF_SIA) + if (*password == '\0' && options.permit_empty_passwd == 0) + return 0; + return auth_sia_password(authctxt, password); +#else struct passwd * pw = authctxt->pw; char *encrypted_password; + char *pw_password; + char *salt; +#if defined(__hpux) || defined(HAVE_SECUREWARE) + struct pr_passwd *spw; +#endif /* __hpux || HAVE_SECUREWARE */ +#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) + struct spwd *spw; +#endif +#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) + struct passwd_adjunct *spw; +#endif +#ifdef WITH_AIXAUTHENTICATE + char *authmsg; + char *loginmsg; + int reenter = 1; +#endif /* deny if no user. */ if (pw == NULL) return 0; - if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) +#ifndef HAVE_CYGWIN + if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) return 0; +#endif if (*password == '\0' && options.permit_empty_passwd == 0) return 0; -#ifdef BSD_AUTH - if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh", - (char *)password) == 0) - return 0; - else - return 1; -#endif #ifdef KRB5 if (options.kerberos_authentication == 1) { - if (auth_krb5_password(pw, password)) - return 1; + int ret = auth_krb5_password(authctxt, password); + if (ret == 1 || ret == 0) + return ret; /* Fall back to ordinary passwd authentication. */ } - -#endif /* KRB5 */ +#endif +#ifdef HAVE_CYGWIN + if (is_winnt) { + HANDLE hToken = cygwin_logon_user(pw, password); + + if (hToken == INVALID_HANDLE_VALUE) + return 0; + cygwin_set_impersonation_token(hToken); + return 1; + } +#endif +#ifdef WITH_AIXAUTHENTICATE + return (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0); +#endif #ifdef KRB4 if (options.kerberos_authentication == 1) { - int ret = auth_krb4_password(pw, password); + int ret = auth_krb4_password(authctxt, password); if (ret == 1 || ret == 0) return ret; /* Fall back to ordinary passwd authentication. */ } #endif +#ifdef BSD_AUTH + if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh", + (char *)password) == 0) + return 0; + else + return 1; +#endif + pw_password = pw->pw_passwd; + + /* + * Various interfaces to shadow or protected password data + */ +#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) + spw = getspnam(pw->pw_name); + if (spw != NULL) + pw_password = spw->sp_pwdp; +#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */ + +#if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) + if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL) + pw_password = spw->pwa_passwd; +#endif /* defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) */ + +#ifdef HAVE_SECUREWARE + if ((spw = getprpwnam(pw->pw_name)) != NULL) + pw_password = spw->ufld.fd_encrypt; +#endif /* HAVE_SECUREWARE */ + +#if defined(__hpux) && !defined(HAVE_SECUREWARE) + if (iscomsec() && (spw = getprpwnam(pw->pw_name)) != NULL) + pw_password = spw->ufld.fd_encrypt; +#endif /* defined(__hpux) && !defined(HAVE_SECUREWARE) */ /* Check for users with no password. */ - if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0) + if ((password[0] == '\0') && (pw_password[0] == '\0')) return 1; - /* Encrypt the candidate password using the proper salt. */ - encrypted_password = crypt(password, - (pw->pw_passwd[0] && pw->pw_passwd[1]) ? pw->pw_passwd : "xx"); + + if (pw_password[0] != '\0') + salt = pw_password; + else + salt = "xx"; + +#ifdef HAVE_MD5_PASSWORDS + if (is_md5_salt(salt)) + encrypted_password = md5_crypt(password, salt); + else + encrypted_password = crypt(password, salt); +#else /* HAVE_MD5_PASSWORDS */ +# if defined(__hpux) && !defined(HAVE_SECUREWARE) + if (iscomsec()) + encrypted_password = bigcrypt(password, salt); + else + encrypted_password = crypt(password, salt); +# else +# ifdef HAVE_SECUREWARE + encrypted_password = bigcrypt(password, salt); +# else + encrypted_password = crypt(password, salt); +# endif /* HAVE_SECUREWARE */ +# endif /* __hpux && !defined(HAVE_SECUREWARE) */ +#endif /* HAVE_MD5_PASSWORDS */ /* Authentication is accepted if the encrypted passwords are identical. */ - return (strcmp(encrypted_password, pw->pw_passwd) == 0); + return (strcmp(encrypted_password, pw_password) == 0); +#endif /* !USE_PAM && !HAVE_OSF_SIA */ } Index: src/crypto/openssh/auth-rh-rsa.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-rh-rsa.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 auth-rh-rsa.c --- src/crypto/openssh/auth-rh-rsa.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/auth-rh-rsa.c 30 Jun 2002 11:37:57 -0000 @@ -13,11 +13,9 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-rh-rsa.c,v 1.23 2001/04/06 21:00:04 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth-rh-rsa.c,v 1.1.1.1.2.4 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: auth-rh-rsa.c,v 1.34 2002/03/25 09:25:06 markus Exp $"); #include "packet.h" -#include "xmalloc.h" #include "uidswap.h" #include "log.h" #include "servconf.h" @@ -25,73 +23,50 @@ #include "hostfile.h" #include "pathnames.h" #include "auth.h" -#include "tildexpand.h" #include "canohost.h" -/* - * Tries to authenticate the user using the .rhosts file and the host using - * its host key. Returns true if authentication succeeds. - */ +#include "monitor_wrap.h" + +/* import */ +extern ServerOptions options; int -auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key) +auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost, + Key *client_host_key) { - extern ServerOptions options; - const char *canonical_hostname; HostStatus host_status; - Key *client_key, *found; - - debug("Trying rhosts with RSA host authentication for client user %.100s", client_user); - - if (pw == NULL || client_host_key == NULL) - return 0; /* Check if we would accept it using rhosts authentication. */ - if (!auth_rhosts(pw, client_user)) + if (!auth_rhosts(pw, cuser)) return 0; - canonical_hostname = get_canonical_hostname( - options.reverse_mapping_check); + host_status = check_key_in_hostfiles(pw, client_host_key, + chost, _PATH_SSH_SYSTEM_HOSTFILE, + options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); - debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname); + return (host_status == HOST_OK); +} - /* wrap the RSA key into a 'generic' key */ - client_key = key_new(KEY_RSA1); - BN_copy(client_key->rsa->e, client_host_key->e); - BN_copy(client_key->rsa->n, client_host_key->n); - found = key_new(KEY_RSA1); - - /* Check if we know the host and its host key. */ - host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE, canonical_hostname, - client_key, found, NULL); - - /* Check user host file unless ignored. */ - if (host_status != HOST_OK && !options.ignore_user_known_hosts) { - struct stat st; - char *user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); - /* - * Check file permissions of _PATH_SSH_USER_HOSTFILE, auth_rsa() - * did already check pw->pw_dir, but there is a race XXX - */ - if (options.strict_modes && - (stat(user_hostfile, &st) == 0) && - ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { - log("Rhosts RSA authentication refused for %.100s: bad owner or modes for %.200s", - pw->pw_name, user_hostfile); - } else { - /* XXX race between stat and the following open() */ - temporarily_use_uid(pw); - host_status = check_host_in_hostfile(user_hostfile, canonical_hostname, - client_key, found, NULL); - restore_uid(); - } - xfree(user_hostfile); - } - key_free(client_key); - key_free(found); +/* + * 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(struct passwd *pw, char *cuser, Key *client_host_key) +{ + char *chost; + + debug("Trying rhosts with RSA host authentication for client user %.100s", + cuser); + + if (pw == NULL || client_host_key == NULL || + client_host_key->rsa == NULL) + return 0; + + chost = (char *)get_canonical_hostname(options.verify_reverse_mapping); + debug("Rhosts RSA authentication: canonical host %.900s", chost); - if (host_status != HOST_OK) { + if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) { debug("Rhosts with RSA host authentication denied: unknown or invalid host key"); packet_send_debug("Your host key cannot be verified: unknown or invalid host key."); return 0; @@ -101,7 +76,7 @@ /* Perform the challenge-response dialog with the client for the host key. */ if (!auth_rsa_challenge_dialog(client_host_key)) { log("Client on %.800s failed to respond correctly to host authentication.", - canonical_hostname); + chost); return 0; } /* @@ -110,7 +85,7 @@ */ verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.", - pw->pw_name, client_user, canonical_hostname); + pw->pw_name, cuser, chost); packet_send_debug("Rhosts with RSA host authentication accepted."); return 1; } Index: src/crypto/openssh/auth-rhosts.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-rhosts.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 auth-rhosts.c --- src/crypto/openssh/auth-rhosts.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/auth-rhosts.c 30 Jun 2002 11:37:57 -0000 @@ -14,10 +14,9 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-rhosts.c,v 1.23 2001/04/12 19:15:24 markus Exp $"); +RCSID("$OpenBSD: auth-rhosts.c,v 1.28 2002/05/13 21:26:49 markus Exp $"); #include "packet.h" -#include "xmalloc.h" #include "uidswap.h" #include "pathnames.h" #include "log.h" @@ -27,6 +26,7 @@ /* import */ extern ServerOptions options; +extern int use_privsep; /* * This function processes an rhosts-style file (.rhosts, .shosts, or @@ -34,7 +34,7 @@ * based on the file, and returns zero otherwise. */ -int +static int check_rhosts_file(const char *filename, const char *hostname, const char *ipaddr, const char *client_user, const char *server_user) @@ -70,7 +70,7 @@ */ switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy)) { case 0: - packet_send_debug("Found empty line in %.100s.", filename); + auth_debug_add("Found empty line in %.100s.", filename); continue; case 1: /* Host name only. */ @@ -80,7 +80,7 @@ /* Got both host and user name. */ break; case 3: - packet_send_debug("Found garbage in %.100s.", filename); + auth_debug_add("Found garbage in %.100s.", filename); continue; default: /* Weird... */ @@ -107,8 +107,8 @@ /* 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); + auth_debug_add("Ignoring wild host/user names in %.100s.", + filename); continue; } /* Verify that host name matches. */ @@ -131,8 +131,8 @@ /* If the entry was negated, deny access. */ if (negated) { - packet_send_debug("Matched negative entry in %.100s.", - filename); + auth_debug_add("Matched negative entry in %.100s.", + filename); return 0; } /* Accept authentication. */ @@ -154,16 +154,14 @@ auth_rhosts(struct passwd *pw, const char *client_user) { const char *hostname, *ipaddr; - int ret; - hostname = get_canonical_hostname(options.reverse_mapping_check); + hostname = get_canonical_hostname(options.verify_reverse_mapping); ipaddr = get_remote_ipaddr(); - ret = auth_rhosts2(pw, client_user, hostname, ipaddr); - return ret; + return auth_rhosts2(pw, client_user, hostname, ipaddr); } -int -auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, +static int +auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname, const char *ipaddr) { char buf[1024]; @@ -186,7 +184,7 @@ * servers. */ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; - rhosts_file_index++) { + rhosts_file_index++) { /* Check users .rhosts or .shosts. */ snprintf(buf, sizeof buf, "%.500s/%.100s", pw->pw_dir, rhosts_files[rhosts_file_index]); @@ -204,16 +202,16 @@ /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */ if (pw->pw_uid != 0) { - if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, client_user, - pw->pw_name)) { - packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.", - hostname, ipaddr); + if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, + client_user, pw->pw_name)) { + auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.", + hostname, ipaddr); return 1; } - if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, client_user, - pw->pw_name)) { - packet_send_debug("Accepted for %.100s [%.100s] by %.100s.", - hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); + if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, + client_user, pw->pw_name)) { + auth_debug_add("Accepted for %.100s [%.100s] by %.100s.", + hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); return 1; } } @@ -222,19 +220,19 @@ * not group or world writable. */ if (stat(pw->pw_dir, &st) < 0) { - log("Rhosts authentication refused for %.100s: no home directory %.200s", - pw->pw_name, pw->pw_dir); - packet_send_debug("Rhosts authentication refused for %.100s: no home directory %.200s", - pw->pw_name, pw->pw_dir); + log("Rhosts authentication refused for %.100s: " + "no home directory %.200s", pw->pw_name, pw->pw_dir); + auth_debug_add("Rhosts authentication refused for %.100s: " + "no home directory %.200s", pw->pw_name, pw->pw_dir); return 0; } if (options.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); + (st.st_mode & 022) != 0)) { + log("Rhosts authentication refused for %.100s: " + "bad ownership or modes for home directory.", pw->pw_name); + auth_debug_add("Rhosts authentication refused for %.100s: " + "bad ownership or modes for home directory.", pw->pw_name); return 0; } /* Temporarily use the user's uid. */ @@ -242,7 +240,7 @@ /* Check all .rhosts files (currently .shosts and .rhosts). */ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; - rhosts_file_index++) { + rhosts_file_index++) { /* Check users .rhosts or .shosts. */ snprintf(buf, sizeof buf, "%.500s/%.100s", pw->pw_dir, rhosts_files[rhosts_file_index]); @@ -257,24 +255,26 @@ */ if (options.strict_modes && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { + (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); + auth_debug_add("Bad file modes for %.200s", buf); continue; } /* Check if we have been configured to ignore .rhosts and .shosts files. */ if (options.ignore_rhosts) { - packet_send_debug("Server has been configured to ignore %.100s.", - rhosts_files[rhosts_file_index]); + auth_debug_add("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]); + auth_debug_add("Accepted by %.100s.", + rhosts_files[rhosts_file_index]); /* Restore the privileged uid. */ restore_uid(); + auth_debug_add("Accepted host %s ip %s client_user %s server_user %s", + hostname, ipaddr, client_user, pw->pw_name); return 1; } } @@ -282,4 +282,17 @@ /* Restore the privileged uid. */ restore_uid(); return 0; +} + +int +auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, + const char *ipaddr) +{ + int ret; + + auth_debug_reset(); + ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr); + if (!use_privsep) + auth_debug_send(); + return ret; } Index: src/crypto/openssh/auth-rsa.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth-rsa.c,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 auth-rsa.c --- src/crypto/openssh/auth-rsa.c 28 Sep 2001 01:33:33 -0000 1.2.2.4 +++ src/crypto/openssh/auth-rsa.c 30 Jun 2002 11:37:57 -0000 @@ -14,8 +14,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-rsa.c,v 1.40 2001/04/06 21:00:07 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth-rsa.c,v 1.2.2.4 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: auth-rsa.c,v 1.56 2002/06/10 16:53:06 stevesk Exp $"); #include #include @@ -32,6 +31,9 @@ #include "log.h" #include "servconf.h" #include "auth.h" +#include "hostfile.h" +#include "monitor_wrap.h" +#include "ssh.h" /* import */ extern ServerOptions options; @@ -52,6 +54,58 @@ * description of the options. */ +BIGNUM * +auth_rsa_generate_challenge(Key *key) +{ + BIGNUM *challenge; + BN_CTX *ctx; + + if ((challenge = BN_new()) == NULL) + fatal("auth_rsa_generate_challenge: BN_new() failed"); + /* Generate a random challenge. */ + BN_rand(challenge, 256, 0, 0); + if ((ctx = BN_CTX_new()) == NULL) + fatal("auth_rsa_generate_challenge: BN_CTX_new() failed"); + BN_mod(challenge, challenge, key->rsa->n, ctx); + BN_CTX_free(ctx); + + return challenge; +} + +int +auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) +{ + u_char buf[32], mdbuf[16]; + MD5_CTX md; + int len; + + /* don't allow short keys */ + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits", + BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); + return (0); + } + + /* The response is MD5 of decrypted challenge plus session id. */ + len = BN_num_bytes(challenge); + if (len <= 0 || len > 32) + fatal("auth_rsa_verify_response: bad challenge length %d", len); + memset(buf, 0, 32); + BN_bn2bin(challenge, buf + 32 - len); + MD5_Init(&md); + MD5_Update(&md, buf, 32); + MD5_Update(&md, session_id, 16); + MD5_Final(mdbuf, &md); + + /* Verify that the response is the original challenge. */ + if (memcmp(response, mdbuf, 16) != 0) { + /* Wrong answer. */ + return (0); + } + /* Correct answer. */ + return (1); +} + /* * Performs the RSA authentication challenge-response dialog with the client, * and returns true (non-zero) if the client gave the correct answer to @@ -59,26 +113,19 @@ */ int -auth_rsa_challenge_dialog(RSA *pk) +auth_rsa_challenge_dialog(Key *key) { BIGNUM *challenge, *encrypted_challenge; - BN_CTX *ctx; - u_char buf[32], mdbuf[16], response[16]; - MD5_CTX md; - u_int i; - int plen, len; + u_char response[16]; + int i, success; - encrypted_challenge = BN_new(); - challenge = BN_new(); + if ((encrypted_challenge = BN_new()) == NULL) + fatal("auth_rsa_challenge_dialog: BN_new() failed"); - /* Generate a random challenge. */ - BN_rand(challenge, 256, 0, 0); - ctx = BN_CTX_new(); - BN_mod(challenge, challenge, pk->n, ctx); - BN_CTX_free(ctx); + challenge = PRIVSEP(auth_rsa_generate_challenge(key)); /* Encrypt the challenge with the public key. */ - rsa_public_encrypt(encrypted_challenge, challenge, pk); + rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); /* Send the encrypted challenge to the client. */ packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); @@ -88,117 +135,67 @@ packet_write_wait(); /* Wait for a response. */ - packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE); - packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE); + packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); for (i = 0; i < 16; i++) response[i] = packet_get_char(); + packet_check_eom(); - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > 32) - fatal("auth_rsa_challenge_dialog: bad challenge length %d", len); - memset(buf, 0, 32); - BN_bn2bin(challenge, buf + 32 - len); - MD5_Init(&md); - MD5_Update(&md, buf, 32); - MD5_Update(&md, session_id, 16); - MD5_Final(mdbuf, &md); + success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); BN_clear_free(challenge); - - /* Verify that the response is the original challenge. */ - if (memcmp(response, mdbuf, 16) != 0) { - /* Wrong answer. */ - return 0; - } - /* Correct answer. */ - return 1; + return (success); } /* - * 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. + * check if there's user key matching client_n, + * return key if login is allowed, NULL otherwise */ int -auth_rsa(struct passwd *pw, BIGNUM *client_n) +auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { - char line[8192], file[MAXPATHLEN]; - int authenticated; + char line[8192], *file; + int allowed = 0; u_int bits; FILE *f; u_long linenum = 0; struct stat st; - RSA *pk; - - /* no user given */ - if (pw == NULL) - return 0; + Key *key; /* Temporarily use the user's uid. */ temporarily_use_uid(pw); /* The authorized keys. */ - snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir, - _PATH_SSH_USER_PERMITTED_KEYS); + file = authorized_keys_file(pw); + debug("trying public RSA key file %s", file); /* Fail quietly if file does not exist */ if (stat(file, &st) < 0) { /* Restore the privileged uid. */ restore_uid(); - return 0; + xfree(file); + return (0); } /* Open the file containing the authorized keys. */ f = fopen(file, "r"); if (!f) { /* Restore the privileged uid. */ restore_uid(); - packet_send_debug("Could not open %.900s for reading.", file); - packet_send_debug("If your home is on an NFS volume, it may need to be world-readable."); - return 0; + xfree(file); + return (0); } - if (options.strict_modes) { - int fail = 0; - char buf[1024]; - /* Check open file in order to avoid open/stat races */ - if (fstat(fileno(f), &st) < 0 || - (st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0) { - snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: " - "bad ownership or modes for '%s'.", pw->pw_name, file); - fail = 1; - } else { - /* Check path to _PATH_SSH_USER_PERMITTED_KEYS */ - int i; - static const char *check[] = { - "", _PATH_SSH_USER_DIR, NULL - }; - for (i = 0; check[i]; i++) { - snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]); - if (stat(line, &st) < 0 || - (st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0) { - snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: " - "bad ownership or modes for '%s'.", pw->pw_name, line); - fail = 1; - break; - } - } - } - if (fail) { - fclose(f); - log("%s", buf); - packet_send_debug("%s", buf); - restore_uid(); - return 0; - } + if (options.strict_modes && + secure_filename(f, file, pw, line, sizeof(line)) != 0) { + xfree(file); + fclose(f); + log("Authentication refused: %s", line); + restore_uid(); + return (0); } - /* Flag indicating whether authentication has succeeded. */ - authenticated = 0; - pk = RSA_new(); - pk->e = BN_new(); - pk->n = BN_new(); + /* Flag indicating whether the key is allowed. */ + allowed = 0; + + key = key_new(KEY_RSA1); /* * Go though the accepted keys, looking for the current key. If @@ -236,24 +233,22 @@ options = NULL; /* Parse the key from the line. */ - if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) { - debug("%.100s, line %lu: bad key syntax", - file, linenum); - packet_send_debug("%.100s, line %lu: bad key syntax", + if (hostfile_read_key(&cp, &bits, key) == 0) { + debug("%.100s, line %lu: non ssh1 key syntax", file, linenum); continue; } /* cp now points to the comment part. */ /* Check if the we have found the desired key (identified by its modulus). */ - if (BN_cmp(pk->n, client_n) != 0) + if (BN_cmp(key->rsa->n, client_n) != 0) continue; /* check the real bits */ - if (bits != BN_num_bits(pk->n)) - log("Warning: %s, line %ld: keysize mismatch: " + if (bits != BN_num_bits(key->rsa->n)) + log("Warning: %s, line %lu: keysize mismatch: " "actual %d vs. announced %d.", - file, linenum, BN_num_bits(pk->n), bits); + file, linenum, BN_num_bits(key->rsa->n), bits); /* We have found the desired key. */ /* @@ -263,22 +258,8 @@ if (!auth_parse_options(pw, options, file, linenum)) continue; - /* Perform the challenge-response dialog for this key. */ - if (!auth_rsa_challenge_dialog(pk)) { - /* Wrong response. */ - verbose("Wrong response to RSA authentication challenge."); - packet_send_debug("Wrong response to RSA authentication challenge."); - continue; - } - /* - * Correct response. The client has been successfully - * authenticated. Note that we have not yet processed the - * options; this will be reset if the options cause the - * authentication to be rejected. - * Break out of the loop if authentication was successful; - * otherwise continue searching. - */ - authenticated = 1; + /* break out, this key is allowed */ + allowed = 1; break; } @@ -286,15 +267,61 @@ restore_uid(); /* Close the file. */ + xfree(file); fclose(f); - RSA_free(pk); - - if (authenticated) - packet_send_debug("RSA authentication accepted."); + /* return key if allowed */ + if (allowed && rkey != NULL) + *rkey = key; else + key_free(key); + return (allowed); +} + +/* + * 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, BIGNUM *client_n) +{ + Key *key; + char *fp; + + /* no user given */ + if (pw == NULL) + return 0; + + if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) { auth_clear_options(); + return (0); + } + + /* Perform the challenge-response dialog for this key. */ + if (!auth_rsa_challenge_dialog(key)) { + /* Wrong response. */ + verbose("Wrong response to RSA authentication challenge."); + packet_send_debug("Wrong response to RSA authentication challenge."); + /* + * Break out of the loop. Otherwise we might send + * another challenge and break the protocol. + */ + key_free(key); + return (0); + } + /* + * Correct response. The client has been successfully + * authenticated. Note that we have not yet processed the + * options; this will be reset if the options cause the + * authentication to be rejected. + */ + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(key), fp); + xfree(fp); + key_free(key); - /* Return authentication result. */ - return authenticated; + packet_send_debug("RSA authentication accepted."); + return (1); } Index: src/crypto/openssh/auth-sia.c =================================================================== RCS file: src/crypto/openssh/auth-sia.c diff -N src/crypto/openssh/auth-sia.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth-sia.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002 Chris Adams. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef HAVE_OSF_SIA +#include "ssh.h" +#include "auth.h" +#include "auth-sia.h" +#include "log.h" +#include "servconf.h" +#include "canohost.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +extern ServerOptions options; +extern int saved_argc; +extern char **saved_argv; + +extern int errno; + +int +auth_sia_password(Authctxt *authctxt, char *pass) +{ + int ret; + SIAENTITY *ent = NULL; + const char *host; + char *user = authctxt->user; + + host = get_canonical_hostname(options.verify_reverse_mapping); + + if (!user || !pass || pass[0] == '\0') + return(0); + + if (sia_ses_init(&ent, saved_argc, saved_argv, host, user, NULL, 0, + NULL) != SIASUCCESS) + return(0); + + if ((ret = sia_ses_authent(NULL, pass, ent)) != SIASUCCESS) { + error("Couldn't authenticate %s from %s", user, host); + if (ret & SIASTOP) + sia_ses_release(&ent); + return(0); + } + + sia_ses_release(&ent); + + return(1); +} + +void +session_setup_sia(char *user, char *tty) +{ + struct passwd *pw; + SIAENTITY *ent = NULL; + const char *host; + + host = get_canonical_hostname (options.verify_reverse_mapping); + + if (sia_ses_init(&ent, saved_argc, saved_argv, host, user, tty, 0, + NULL) != SIASUCCESS) { + fatal("sia_ses_init failed"); + } + + if ((pw = getpwnam(user)) == NULL) { + sia_ses_release(&ent); + fatal("getpwnam: no user: %s", user); + } + if (sia_make_entity_pwd(pw, ent) != SIASUCCESS) { + sia_ses_release(&ent); + fatal("sia_make_entity_pwd failed"); + } + + ent->authtype = SIA_A_NONE; + if (sia_ses_estab(sia_collect_trm, ent) != SIASUCCESS) { + fatal("Couldn't establish session for %s from %s", user, + host); + } + + if (setpriority(PRIO_PROCESS, 0, 0) == -1) { + sia_ses_release(&ent); + fatal("setpriority: %s", strerror (errno)); + } + + if (sia_ses_launch(sia_collect_trm, ent) != SIASUCCESS) { + fatal("Couldn't launch session for %s from %s", user, host); + } + + sia_ses_release(&ent); + + if (setreuid(geteuid(), geteuid()) < 0) { + fatal("setreuid: %s", strerror(errno)); + } +} + +#endif /* HAVE_OSF_SIA */ Index: src/crypto/openssh/auth-sia.h =================================================================== RCS file: src/crypto/openssh/auth-sia.h diff -N src/crypto/openssh/auth-sia.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth-sia.h 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2002 Chris Adams. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef HAVE_OSF_SIA + +int auth_sia_password(Authctxt *authctxt, char *pass); +void session_setup_sia(char *user, char *tty); + +#endif /* HAVE_OSF_SIA */ Index: src/crypto/openssh/auth-skey.c =================================================================== RCS file: src/crypto/openssh/auth-skey.c diff -N src/crypto/openssh/auth-skey.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth-skey.c 28 Sep 2001 01:33:33 -0000 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "includes.h" +RCSID("$OpenBSD: auth-skey.c,v 1.19 2002/06/19 00:27:55 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/auth-skey.c,v 1.13 2002/06/29 10:44:34 des Exp $"); + +#ifdef SKEY + +#ifdef OPIE +#include +#define skey opie +#define skeychallenge(k, u, c) opiechallenge((k), (u), (c)) +#define skey_haskey(u) opie_haskey((u)) +#define skey_passcheck(u, r) opie_passverify((u), (r)) +#else +#include +#endif + +#include "xmalloc.h" +#include "auth.h" +#include "monitor_wrap.h" + +static void * +skey_init_ctx(Authctxt *authctxt) +{ + return authctxt; +} + +int +skey_query(void *ctx, char **name, char **infotxt, + u_int* numprompts, char ***prompts, u_int **echo_on) +{ + Authctxt *authctxt = ctx; + char challenge[1024], *p; + int len; + struct skey skey; + + if (skeychallenge(&skey, authctxt->user, challenge) == -1) + return -1; + + *name = xstrdup(""); + *infotxt = xstrdup(""); + *numprompts = 1; + *prompts = xmalloc(*numprompts * sizeof(char*)); + *echo_on = xmalloc(*numprompts * sizeof(u_int)); + (*echo_on)[0] = 0; + + len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; + p = xmalloc(len); + strlcpy(p, challenge, len); + strlcat(p, SKEY_PROMPT, len); + (*prompts)[0] = p; + + return 0; +} + +int +skey_respond(void *ctx, u_int numresponses, char **responses) +{ + Authctxt *authctxt = ctx; + + if (authctxt->valid && + numresponses == 1 && + skey_haskey(authctxt->pw->pw_name) == 0 && + skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1) + return 0; + return -1; +} + +static void +skey_free_ctx(void *ctx) +{ + /* we don't have a special context */ +} + +KbdintDevice skey_device = { + "skey", + skey_init_ctx, + skey_query, + skey_respond, + skey_free_ctx +}; + +KbdintDevice mm_skey_device = { + "skey", + skey_init_ctx, + mm_skey_query, + mm_skey_respond, + skey_free_ctx +}; +#endif /* SKEY */ Index: src/crypto/openssh/auth.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth.c,v retrieving revision 1.3.2.4 diff -u -u -r1.3.2.4 auth.c --- src/crypto/openssh/auth.c 28 Sep 2001 01:33:33 -0000 1.3.2.4 +++ src/crypto/openssh/auth.c 30 Jun 2002 11:37:57 -0000 @@ -23,8 +23,18 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth.c,v 1.3.2.4 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: auth.c,v 1.43 2002/05/17 14:27:55 millert Exp $"); + +#ifdef HAVE_LOGIN_H +#include +#endif +#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) +#include +#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */ + +#ifdef HAVE_LIBGEN_H +#include +#endif #include "xmalloc.h" #include "match.h" @@ -34,10 +44,21 @@ #include "auth.h" #include "auth-options.h" #include "canohost.h" +#include "buffer.h" +#include "bufaux.h" +#include "uidswap.h" +#include "tildexpand.h" +#include "misc.h" +#include "bufaux.h" +#include "packet.h" /* import */ extern ServerOptions options; +/* Debugging messages */ +Buffer auth_debug; +int auth_debug_init; + /* * Check if the user is allowed to log in via ssh. If user is listed * in DenyUsers or one of user's groups is listed in DenyGroups, false @@ -51,13 +72,56 @@ allowed_user(struct passwd * pw) { struct stat st; + const char *hostname = NULL, *ipaddr = NULL; char *shell; int i; +#ifdef WITH_AIXAUTHENTICATE + char *loginmsg; +#endif /* WITH_AIXAUTHENTICATE */ +#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \ + !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE) + struct spwd *spw; /* Shouldn't be called if pw is NULL, but better safe than sorry... */ if (!pw || !pw->pw_name) return 0; +#define DAY (24L * 60 * 60) /* 1 day in seconds */ + spw = getspnam(pw->pw_name); + if (spw != NULL) { + time_t today = time(NULL) / DAY; + debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" + " sp_max %d", (int)today, (int)spw->sp_expire, + (int)spw->sp_lstchg, (int)spw->sp_max); + + /* + * We assume account and password expiration occurs the + * day after the day specified. + */ + if (spw->sp_expire != -1 && today > spw->sp_expire) { + log("Account %.100s has expired", pw->pw_name); + return 0; + } + + if (spw->sp_lstchg == 0) { + log("User %.100s password has expired (root forced)", + pw->pw_name); + return 0; + } + + if (spw->sp_max != -1 && + today > spw->sp_lstchg + spw->sp_max) { + log("User %.100s password has expired (password aged)", + pw->pw_name); + return 0; + } + } +#else + /* Shouldn't be called if pw is NULL, but better safe than sorry... */ + if (!pw || !pw->pw_name) + return 0; +#endif + /* * Get the shell from the password data. An empty shell field is * legal, and means /bin/sh. @@ -65,36 +129,61 @@ shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; /* deny if shell does not exists or is not executable */ - if (stat(shell, &st) != 0) + if (stat(shell, &st) != 0) { + log("User %.100s not allowed because shell %.100s does not exist", + pw->pw_name, shell); return 0; - if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) + } + if (S_ISREG(st.st_mode) == 0 || + (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { + log("User %.100s not allowed because shell %.100s is not executable", + pw->pw_name, shell); return 0; + } + + if (options.num_deny_users > 0 || options.num_allow_users > 0) { + hostname = get_canonical_hostname(options.verify_reverse_mapping); + ipaddr = get_remote_ipaddr(); + } /* Return false if user is listed in DenyUsers */ if (options.num_deny_users > 0) { for (i = 0; i < options.num_deny_users; i++) - if (match_pattern(pw->pw_name, options.deny_users[i])) + if (match_user(pw->pw_name, hostname, ipaddr, + options.deny_users[i])) { + log("User %.100s not allowed because listed in DenyUsers", + pw->pw_name); return 0; + } } /* Return false if AllowUsers isn't empty and user isn't listed there */ if (options.num_allow_users > 0) { for (i = 0; i < options.num_allow_users; i++) - if (match_pattern(pw->pw_name, options.allow_users[i])) + if (match_user(pw->pw_name, hostname, ipaddr, + options.allow_users[i])) break; /* i < options.num_allow_users iff we break for loop */ - if (i >= options.num_allow_users) + if (i >= options.num_allow_users) { + log("User %.100s not allowed because not listed in AllowUsers", + pw->pw_name); return 0; + } } if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { /* Get the user's group access list (primary and supplementary) */ - if (ga_init(pw->pw_name, pw->pw_gid) == 0) + if (ga_init(pw->pw_name, pw->pw_gid) == 0) { + log("User %.100s not allowed because not in any group", + pw->pw_name); return 0; + } /* Return false if one of user's groups is listed in DenyGroups */ if (options.num_deny_groups > 0) if (ga_match(options.deny_groups, options.num_deny_groups)) { ga_free(); + log("User %.100s not allowed because a group is listed in DenyGroups", + pw->pw_name); return 0; } /* @@ -105,10 +194,30 @@ if (!ga_match(options.allow_groups, options.num_allow_groups)) { ga_free(); + log("User %.100s not allowed because none of user's groups are listed in AllowGroups", + pw->pw_name); return 0; } ga_free(); } + +#ifdef WITH_AIXAUTHENTICATE + if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) { + if (loginmsg && *loginmsg) { + /* Remove embedded newlines (if any) */ + char *p; + for (p = loginmsg; *p; p++) { + if (*p == '\n') + *p = ' '; + } + /* Remove trailing newline */ + *--p = '\0'; + log("Login restricted for %s: %.100s", pw->pw_name, loginmsg); + } + return 0; + } +#endif /* WITH_AIXAUTHENTICATE */ + /* We found no reason not to let this user try to log on... */ return 1; } @@ -143,7 +252,7 @@ authmsg, method, authctxt->valid ? "" : "illegal user ", - authctxt->valid && authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user, + authctxt->user, get_remote_ipaddr(), get_remote_port(), info); @@ -172,4 +281,259 @@ } log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); return 0; +} + + +/* + * Given a template and a passwd structure, build a filename + * by substituting % tokenised options. Currently, %% becomes '%', + * %h becomes the home directory and %u the username. + * + * This returns a buffer allocated by xmalloc. + */ +char * +expand_filename(const char *filename, struct passwd *pw) +{ + Buffer buffer; + char *file; + const char *cp; + + /* + * Build the filename string in the buffer by making the appropriate + * substitutions to the given file name. + */ + buffer_init(&buffer); + for (cp = filename; *cp; cp++) { + if (cp[0] == '%' && cp[1] == '%') { + buffer_append(&buffer, "%", 1); + cp++; + continue; + } + if (cp[0] == '%' && cp[1] == 'h') { + buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir)); + cp++; + continue; + } + if (cp[0] == '%' && cp[1] == 'u') { + buffer_append(&buffer, pw->pw_name, + strlen(pw->pw_name)); + cp++; + continue; + } + buffer_append(&buffer, cp, 1); + } + buffer_append(&buffer, "\0", 1); + + /* + * Ensure that filename starts anchored. If not, be backward + * compatible and prepend the '%h/' + */ + file = xmalloc(MAXPATHLEN); + cp = buffer_ptr(&buffer); + if (*cp != '/') + snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp); + else + strlcpy(file, cp, MAXPATHLEN); + + buffer_free(&buffer); + return file; +} + +char * +authorized_keys_file(struct passwd *pw) +{ + return expand_filename(options.authorized_keys_file, pw); +} + +char * +authorized_keys_file2(struct passwd *pw) +{ + return expand_filename(options.authorized_keys_file2, pw); +} + +/* return ok if key exists in sysfile or userfile */ +HostStatus +check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, + const char *sysfile, const char *userfile) +{ + Key *found; + char *user_hostfile; + struct stat st; + HostStatus host_status; + + /* Check if we know the host and its host key. */ + found = key_new(key->type); + host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); + + if (host_status != HOST_OK && userfile != NULL) { + user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); + if (options.strict_modes && + (stat(user_hostfile, &st) == 0) && + ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || + (st.st_mode & 022) != 0)) { + log("Authentication refused for %.100s: " + "bad owner or modes for %.200s", + pw->pw_name, user_hostfile); + } else { + temporarily_use_uid(pw); + host_status = check_host_in_hostfile(user_hostfile, + host, key, found, NULL); + restore_uid(); + } + xfree(user_hostfile); + } + key_free(found); + + debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ? + "ok" : "not found", host); + return host_status; +} + + +/* + * Check a given file for security. This is defined as all components + * of the path to the file must either be owned by either the owner of + * of the file or root and no directories must be group or world writable. + * + * XXX Should any specific check be done for sym links ? + * + * Takes an open file descriptor, the file name, a uid and and + * error buffer plus max size as arguments. + * + * Returns 0 on success and -1 on failure + */ +int +secure_filename(FILE *f, const char *file, struct passwd *pw, + char *err, size_t errlen) +{ + uid_t uid = pw->pw_uid; + char buf[MAXPATHLEN], homedir[MAXPATHLEN]; + char *cp; + struct stat st; + + if (realpath(file, buf) == NULL) { + snprintf(err, errlen, "realpath %s failed: %s", file, + strerror(errno)); + return -1; + } + if (realpath(pw->pw_dir, homedir) == NULL) { + snprintf(err, errlen, "realpath %s failed: %s", pw->pw_dir, + strerror(errno)); + return -1; + } + + /* check the open file to avoid races */ + if (fstat(fileno(f), &st) < 0 || + (st.st_uid != 0 && st.st_uid != uid) || + (st.st_mode & 022) != 0) { + snprintf(err, errlen, "bad ownership or modes for file %s", + buf); + return -1; + } + + /* for each component of the canonical path, walking upwards */ + for (;;) { + if ((cp = dirname(buf)) == NULL) { + snprintf(err, errlen, "dirname() failed"); + return -1; + } + strlcpy(buf, cp, sizeof(buf)); + + debug3("secure_filename: checking '%s'", buf); + if (stat(buf, &st) < 0 || + (st.st_uid != 0 && st.st_uid != uid) || + (st.st_mode & 022) != 0) { + snprintf(err, errlen, + "bad ownership or modes for directory %s", buf); + return -1; + } + + /* If are passed the homedir then we can stop */ + if (strcmp(homedir, buf) == 0) { + debug3("secure_filename: terminating check at '%s'", + buf); + break; + } + /* + * dirname should always complete with a "/" path, + * but we can be paranoid and check for "." too + */ + if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) + break; + } + return 0; +} + +struct passwd * +getpwnamallow(const char *user) +{ +#ifdef HAVE_LOGIN_CAP + extern login_cap_t *lc; +#ifdef BSD_AUTH + auth_session_t *as; +#endif +#endif + struct passwd *pw; + + pw = getpwnam(user); + if (pw == NULL || !allowed_user(pw)) + return (NULL); +#ifdef HAVE_LOGIN_CAP + if ((lc = login_getclass(pw->pw_class)) == NULL) { + debug("unable to get login class: %s", user); + return (NULL); + } +#ifdef BSD_AUTH + if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || + auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { + debug("Approval failure for %s", user); + pw = NULL; + } + if (as != NULL) + auth_close(as); +#endif +#endif + if (pw != NULL) + return (pwcopy(pw)); + return (NULL); +} + +void +auth_debug_add(const char *fmt,...) +{ + char buf[1024]; + va_list args; + + if (!auth_debug_init) + return; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + buffer_put_cstring(&auth_debug, buf); +} + +void +auth_debug_send(void) +{ + char *msg; + + if (!auth_debug_init) + return; + while (buffer_len(&auth_debug)) { + msg = buffer_get_string(&auth_debug, NULL); + packet_send_debug("%s", msg); + xfree(msg); + } +} + +void +auth_debug_reset(void) +{ + if (auth_debug_init) + buffer_clear(&auth_debug); + else { + buffer_init(&auth_debug); + auth_debug_init = 1; + } } Index: src/crypto/openssh/auth.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth.h,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 auth.h --- src/crypto/openssh/auth.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/auth.h 30 Jun 2002 11:37:57 -0000 @@ -1,3 +1,6 @@ +/* $OpenBSD: auth.h,v 1.39 2002/05/31 11:35:15 markus Exp $ */ +/* $FreeBSD: src/crypto/openssh/auth.h,v 1.8 2002/06/29 10:44:36 des Exp $ */ + /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -21,12 +24,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $OpenBSD: auth.h,v 1.15 2001/04/12 19:15:24 markus Exp $ - * $FreeBSD: src/crypto/openssh/auth.h,v 1.1.1.1.2.4 2001/09/28 01:33:33 green Exp $ */ + #ifndef AUTH_H #define AUTH_H +#include "key.h" +#include "hostfile.h" #include #ifdef HAVE_LOGIN_CAP @@ -35,121 +39,162 @@ #ifdef BSD_AUTH #include #endif +#ifdef KRB5 +#include +#endif typedef struct Authctxt Authctxt; +typedef struct Authmethod Authmethod; +typedef struct KbdintDevice KbdintDevice; + struct Authctxt { - int success; - int postponed; - int valid; - int attempt; - int failures; - char *user; - char *service; - struct passwd *pw; - char *style; + int success; + int postponed; + int valid; + int attempt; + int failures; + char *user; + char *service; + struct passwd *pw; + char *style; + void *kbdintctxt; #ifdef BSD_AUTH - auth_session_t *as; + auth_session_t *as; +#endif +#ifdef KRB4 + char *krb4_ticket_file; +#endif +#ifdef KRB5 + krb5_context krb5_ctx; + krb5_auth_context krb5_auth_ctx; + krb5_ccache krb5_fwd_ccache; + krb5_principal krb5_user; + char *krb5_ticket_file; #endif }; -/* - * 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). - */ -int auth_rhosts(struct passwd * pw, const char *client_user); - -/* extended interface similar to auth_rhosts() */ -int -auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, - const char *ipaddr); - -/* - * 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(struct passwd * pw, const char *client_user, RSA* client_host_key); - -/* - * Tries to authenticate the user using password. Returns true if - * authentication succeeds. - */ -int auth_password(Authctxt *authctxt, 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, BIGNUM * client_n); +struct Authmethod { + char *name; + int (*userauth)(Authctxt *authctxt); + int *enabled; +}; /* - * 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, u_int *bitsp, BIGNUM * e, BIGNUM * n); + * Keyboard interactive device: + * init_ctx returns: non NULL upon success + * query returns: 0 - success, otherwise failure + * respond returns: 0 - success, 1 - need further interaction, + * otherwise - failure + */ +struct KbdintDevice +{ + const char *name; + void* (*init_ctx)(Authctxt*); + int (*query)(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on); + int (*respond)(void *ctx, u_int numresp, char **responses); + void (*free_ctx)(void *ctx); +}; -/* - * 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(RSA *pk); +int auth_rhosts(struct passwd *, const char *); +int +auth_rhosts2(struct passwd *, const char *, const char *, const char *); -#ifdef KRB4 -#include -#endif /* KRB4 */ -#ifdef KRB5 -#include -int auth_krb5(); /* XXX Doplnit prototypy */ -int auth_krb5_tgt(); -int krb5_init(); -void krb5_cleanup_proc(void *ignore); -int auth_krb5_password(struct passwd *pw, const char *password); -#endif /* KRB5 */ +int auth_rhosts_rsa(struct passwd *, char *, Key *); +int auth_password(Authctxt *, const char *); +int auth_rsa(struct passwd *, BIGNUM *); +int auth_rsa_challenge_dialog(Key *); +BIGNUM *auth_rsa_generate_challenge(Key *); +int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]); +int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); + +int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); +int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); +int user_key_allowed(struct passwd *, Key *); #ifdef KRB4 #include -/* - * Performs Kerberos v4 mutual authentication 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_krb4(const char *server_user, KTEXT auth, char **client); -int krb4_init(uid_t uid); -void krb4_cleanup_proc(void *ignore); -int auth_krb4_password(struct passwd * pw, const char *password); +int auth_krb4(Authctxt *, KTEXT, char **); +int auth_krb4_password(Authctxt *, const char *); +void krb4_cleanup_proc(void *); #ifdef AFS #include +int auth_krb4_tgt(Authctxt *, const char *); +int auth_afs_token(Authctxt *, const char *); +#endif /* AFS */ -/* Accept passed Kerberos v4 ticket-granting ticket and AFS tokens. */ -int auth_kerberos_tgt(struct passwd * pw, const char *string); -int auth_afs_token(struct passwd * pw, const char *token_string); -#endif /* AFS */ +#endif /* KRB4 */ + +#ifdef KRB5 +int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client); +int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt); +int auth_krb5_password(Authctxt *authctxt, const char *password); +void krb5_cleanup_proc(void *authctxt); +#endif /* KRB5 */ -#endif /* KRB4 */ +#include "auth-pam.h" +#include "auth2-pam.h" -void do_authentication(void); -void do_authentication2(void); +Authctxt *do_authentication(void); +Authctxt *do_authentication2(void); Authctxt *authctxt_new(void); -void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info); -void userauth_finish(Authctxt *authctxt, int authenticated, char *method); -int auth_root_allowed(char *method); - -int auth2_challenge(Authctxt *authctxt, char *devs); +void auth_log(Authctxt *, int, char *, char *); +void userauth_finish(Authctxt *, int, char *); +int auth_root_allowed(char *); + +char *auth2_read_banner(void); + +void privsep_challenge_enable(void); + +int auth2_challenge(Authctxt *, char *); +void auth2_challenge_stop(Authctxt *); +int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); +int bsdauth_respond(void *, u_int, char **); +int skey_query(void *, char **, char **, u_int *, char ***, u_int **); +int skey_respond(void *, u_int, char **); -int allowed_user(struct passwd * pw); +int allowed_user(struct passwd *); +struct passwd * getpwnamallow(const char *user); -char *get_challenge(Authctxt *authctxt, char *devs); -int verify_response(Authctxt *authctxt, char *response); +char *get_challenge(Authctxt *); +int verify_response(Authctxt *, const char *); struct passwd * auth_get_user(void); +char *expand_filename(const char *, struct passwd *); +char *authorized_keys_file(struct passwd *); +char *authorized_keys_file2(struct passwd *); + +int +secure_filename(FILE *, const char *, struct passwd *, char *, size_t); + +HostStatus +check_key_in_hostfiles(struct passwd *, Key *, const char *, + const char *, const char *); + +/* hostkey handling */ +Key *get_hostkey_by_index(int); +Key *get_hostkey_by_type(int); +int get_hostkey_index(Key *); +int ssh1_session_key(BIGNUM *); + +/* debug messages during authentication */ +void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); +void auth_debug_send(void); +void auth_debug_reset(void); + #define AUTH_FAIL_MAX 6 #define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) #define AUTH_FAIL_MSG "Too many authentication failures for %.100s" + +#ifdef SKEY +#ifdef OPIE +#define SKEY_PROMPT "\nOPIE Password: " +#else +#define SKEY_PROMPT "\nS/Key Password: " +#endif +#endif #endif Index: src/crypto/openssh/auth1.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth1.c,v retrieving revision 1.3.2.7 diff -u -u -r1.3.2.7 auth1.c --- src/crypto/openssh/auth1.c 28 Sep 2001 01:33:33 -0000 1.3.2.7 +++ src/crypto/openssh/auth1.c 30 Jun 2002 11:37:57 -0000 @@ -10,8 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth1.c,v 1.22 2001/03/23 12:02:49 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth1.c,v 1.3.2.7 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: auth1.c,v 1.41 2002/06/19 00:27:55 deraadt Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -23,18 +22,10 @@ #include "servconf.h" #include "compat.h" #include "auth.h" -#include "auth-pam.h" +#include "channels.h" #include "session.h" -#include "canohost.h" -#include "misc.h" -#include -#include - -#ifdef KRB5 -extern krb5_context ssh_context; -krb5_principal tkt_client = NULL; /* Principal from the received ticket. -Also is used as an indication of succesful krb5 authentization. */ -#endif +#include "uidswap.h" +#include "monitor_wrap.h" /* import */ extern ServerOptions options; @@ -42,7 +33,7 @@ /* * convert ssh auth msg type into description */ -char * +static char * get_authname(int type) { static char buf[1024]; @@ -71,65 +62,29 @@ * read packets, try to authenticate the user and * return only if authentication is successful */ -void +static void do_authloop(Authctxt *authctxt) { int authenticated = 0; u_int bits; - RSA *client_host_key; + Key *client_host_key; BIGNUM *n; char *client_user, *password; char info[1024]; u_int dlen; - int plen, nlen, elen; u_int ulen; int type = 0; struct passwd *pw = authctxt->pw; - void (*authlog) (const char *fmt,...) = verbose; -#ifdef HAVE_LOGIN_CAP - login_cap_t *lc; -#endif /* HAVE_LOGIN_CAP */ -#ifdef USE_PAM - struct inverted_pam_cookie *pam_cookie; -#endif /* USE_PAM */ -#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS) - const char *from_host, *from_ip; - - from_host = get_canonical_hostname(options.reverse_mapping_check); - from_ip = get_remote_ipaddr(); -#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */ -#if 0 -#ifdef KRB5 - { - krb5_error_code ret; - - ret = krb5_init_context(&ssh_context); - if (ret) - verbose("Error while initializing Kerberos V5."); - krb5_init_ets(ssh_context); - - } -#endif /* KRB5 */ -#endif debug("Attempting authentication for %s%.100s.", - authctxt->valid ? "" : "illegal user ", authctxt->user); + authctxt->valid ? "" : "illegal user ", authctxt->user); /* If the user has no password, accept authentication immediately. */ if (options.password_authentication && #if defined(KRB4) || defined(KRB5) - (!options.kerberos_authentication -#if defined(KRB4) - || options.krb4_or_local_passwd -#endif - ) && + (!options.kerberos_authentication || options.kerberos_or_local_passwd) && #endif -#ifdef USE_PAM - auth_pam_password(authctxt, "") -#else - auth_password(authctxt, "") -#endif - ) { + PRIVSEP(auth_password(authctxt, ""))) { auth_log(authctxt, 1, "without authentication", ""); return; } @@ -148,101 +103,65 @@ info[0] = '\0'; /* Get a packet from the client. */ - type = packet_read(&plen); + type = packet_read(); /* Process the packet. */ switch (type) { -#ifdef AFS -#ifndef KRB5 - case SSH_CMSG_HAVE_KERBEROS_TGT: - if (!options.krb4_tgt_passing) { - /* packet_get_all(); */ - verbose("Kerberos v4 tgt passing disabled."); - break; - } else { - /* Accept Kerberos v4 tgt. */ - char *tgt = packet_get_string(&dlen); - packet_integrity_check(plen, 4 + dlen, type); - if (!auth_krb4_tgt(pw, tgt)) - verbose("Kerberos v4 tgt REFUSED for %.100ss", authctxt->user); - xfree(tgt); - } - continue; -#endif /* !KRB5 */ - case SSH_CMSG_HAVE_AFS_TOKEN: - if (!options.afs_token_passing || !k_hasafs()) { - verbose("AFS token passing disabled."); - break; - } else { - /* Accept AFS token. */ - char *token_string = packet_get_string(&dlen); - packet_integrity_check(plen, 4 + dlen, type); - if (!auth_afs_token(pw, token_string)) - verbose("AFS token REFUSED for %.100s", authctxt->user); - xfree(token_string); - } - continue; -#endif /* AFS */ + #if defined(KRB4) || defined(KRB5) case SSH_CMSG_AUTH_KERBEROS: if (!options.kerberos_authentication) { verbose("Kerberos authentication disabled."); - break; } else { - /* Try Kerberos authentication. */ - u_int len; - char *tkt_user = NULL; - char *kdata = packet_get_string(&len); - packet_integrity_check(plen, 4 + len, type); - - if (!authctxt->valid) { - /* Do nothing. */ - } else if (kdata[0] == 4) { /* 4 == KRB_PROT_VERSION */ + char *kdata = packet_get_string(&dlen); + packet_check_eom(); + + if (kdata[0] == 4) { /* KRB_PROT_VERSION */ #ifdef KRB4 - KTEXT_ST auth; + KTEXT_ST tkt; - auth.length = len; - if (auth.length < MAX_KTXT_LEN) - memcpy(auth.dat, kdata, auth.length); - authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user); - - if (authenticated) { - snprintf(info, sizeof info, - " tktuser %.100s", tkt_user); - xfree(tkt_user); + tkt.length = dlen; + if (tkt.length < MAX_KTXT_LEN) + memcpy(tkt.dat, kdata, tkt.length); + + if (auth_krb4(authctxt, &tkt, &client_user)) { + authenticated = 1; + snprintf(info, sizeof(info), + " tktuser %.100s", + client_user); } -#else - verbose("Kerberos v4 authentication disabled."); #endif /* KRB4 */ } else { -#ifndef KRB5 - verbose("Kerberos v5 authentication disabled."); -#else - krb5_data k5data; - k5data.length = len; - k5data.data = kdata; - #if 0 - if (krb5_init_context(&ssh_context)) { - verbose("Error while initializing Kerberos V5."); - break; - } - krb5_init_ets(ssh_context); - #endif - /* pw->name is passed just for logging purposes */ - if (auth_krb5(pw->pw_name, &k5data, &tkt_client)) { - /* authorize client against .k5login */ - if (krb5_kuserok(ssh_context, - tkt_client, - pw->pw_name)) - authenticated = 1; +#ifdef KRB5 + krb5_data tkt; + tkt.length = dlen; + tkt.data = kdata; + + if (auth_krb5(authctxt, &tkt, &client_user)) { + authenticated = 1; + snprintf(info, sizeof(info), + " tktuser %.100s", + client_user); } #endif /* KRB5 */ - } + } xfree(kdata); - } - break; + } + break; #endif /* KRB4 || KRB5 */ +#if defined(AFS) || defined(KRB5) + /* XXX - punt on backward compatibility here. */ + case SSH_CMSG_HAVE_KERBEROS_TGT: + packet_send_debug("Kerberos TGT passing disabled before authentication."); + break; +#ifdef AFS + case SSH_CMSG_HAVE_AFS_TOKEN: + packet_send_debug("AFS token passing disabled before authentication."); + break; +#endif /* AFS */ +#endif /* AFS || KRB5 */ + case SSH_CMSG_AUTH_RHOSTS: if (!options.rhosts_authentication) { verbose("Rhosts authentication disabled."); @@ -255,7 +174,7 @@ * IP-spoofing on a local network.) */ client_user = packet_get_string(&ulen); - packet_integrity_check(plen, 4 + ulen, type); + packet_check_eom(); /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ authenticated = auth_rhosts(pw, client_user); @@ -276,24 +195,20 @@ client_user = packet_get_string(&ulen); /* Get the client host key. */ - client_host_key = RSA_new(); - if (client_host_key == NULL) - fatal("RSA_new failed"); - client_host_key->e = BN_new(); - client_host_key->n = BN_new(); - if (client_host_key->e == NULL || client_host_key->n == NULL) - fatal("BN_new failed"); + client_host_key = key_new(KEY_RSA1); bits = packet_get_int(); - packet_get_bignum(client_host_key->e, &elen); - packet_get_bignum(client_host_key->n, &nlen); + packet_get_bignum(client_host_key->rsa->e); + packet_get_bignum(client_host_key->rsa->n); - if (bits != BN_num_bits(client_host_key->n)) + if (bits != BN_num_bits(client_host_key->rsa->n)) verbose("Warning: keysize mismatch for client_host_key: " - "actual %d, announced %d", BN_num_bits(client_host_key->n), bits); - packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type); - - authenticated = auth_rhosts_rsa(pw, client_user, client_host_key); - RSA_free(client_host_key); + "actual %d, announced %d", + BN_num_bits(client_host_key->rsa->n), bits); + packet_check_eom(); + + authenticated = auth_rhosts_rsa(pw, client_user, + client_host_key); + key_free(client_host_key); snprintf(info, sizeof info, " ruser %.100s", client_user); break; @@ -304,9 +219,10 @@ break; } /* RSA authentication requested. */ - n = BN_new(); - packet_get_bignum(n, &nlen); - packet_integrity_check(plen, nlen, type); + if ((n = BN_new()) == NULL) + fatal("do_authloop: BN_new failed"); + packet_get_bignum(n); + packet_check_eom(); authenticated = auth_rsa(pw, n); BN_clear_free(n); break; @@ -322,62 +238,24 @@ * not visible to an outside observer. */ password = packet_get_string(&dlen); - packet_integrity_check(plen, 4 + dlen, type); + packet_check_eom(); -#ifdef USE_PAM - /* Do PAM auth with password */ - authenticated = auth_pam_password(authctxt, password); -#else /* !USE_PAM */ - /* Try authentication with the password. */ - authenticated = auth_password(authctxt, password); -#endif /* USE_PAM */ + /* Try authentication with the password. */ + authenticated = PRIVSEP(auth_password(authctxt, password)); memset(password, 0, strlen(password)); xfree(password); break; -#ifdef USE_PAM - case SSH_CMSG_AUTH_TIS: - debug("rcvd SSH_CMSG_AUTH_TIS: Trying PAM"); - pam_cookie = ipam_start_auth("csshd", pw->pw_name); - /* We now have data available to send as a challenge */ - if (pam_cookie->num_msg != 1 || - (pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_OFF && - pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_ON)) { - /* We got several challenges or an unknown challenge type */ - ipam_free_cookie(pam_cookie); - pam_cookie = NULL; - break; - } - packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); - packet_put_string(pam_cookie->msg[0]->msg, strlen(pam_cookie->msg[0]->msg)); - packet_send(); - packet_write_wait(); - continue; - case SSH_CMSG_AUTH_TIS_RESPONSE: - debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); - if (pam_cookie == NULL) - break; - { - char *response = packet_get_string(&dlen); - - packet_integrity_check(plen, 4 + dlen, type); - pam_cookie->resp[0]->resp = strdup(response); - xfree(response); - authenticated = ipam_complete_auth(pam_cookie); - ipam_free_cookie(pam_cookie); - pam_cookie = NULL; - } - break; -#elif defined(SKEY) case SSH_CMSG_AUTH_TIS: debug("rcvd SSH_CMSG_AUTH_TIS"); - if (options.challenge_reponse_authentication == 1) { - char *challenge = get_challenge(authctxt, authctxt->style); + if (options.challenge_response_authentication == 1) { + char *challenge = get_challenge(authctxt); if (challenge != NULL) { debug("sending challenge '%s'", challenge); packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); packet_put_cstring(challenge); + xfree(challenge); packet_send(); packet_write_wait(); continue; @@ -386,47 +264,15 @@ break; case SSH_CMSG_AUTH_TIS_RESPONSE: debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE"); - if (options.challenge_reponse_authentication == 1) { + if (options.challenge_response_authentication == 1) { char *response = packet_get_string(&dlen); debug("got response '%s'", response); - packet_integrity_check(plen, 4 + dlen, type); + packet_check_eom(); authenticated = verify_response(authctxt, response); memset(response, 'r', dlen); xfree(response); } break; -#else - case SSH_CMSG_AUTH_TIS: - /* TIS Authentication is unsupported */ - log("TIS authentication unsupported."); - break; -#endif -#ifdef KRB5 - case SSH_CMSG_HAVE_KERBEROS_TGT: - /* Passing krb5 ticket */ - if (!options.krb5_tgt_passing - /*|| !options.krb5_authentication */) { - verbose("Kerberos v5 tgt passing disabled."); - break; - } - - if (tkt_client == NULL) { - /* passing tgt without krb5 authentication */ - } - - { - krb5_data tgt; - u_int tgtlen; - tgt.data = packet_get_string(&tgtlen); - tgt.length = tgtlen; - - if (!auth_krb5_tgt(pw->pw_name, &tgt, tkt_client)) - verbose ("Kerberos V5 TGT refused for %.100s", pw->pw_name); - xfree(tgt.data); - - break; - } -#endif /* KRB5 */ default: /* @@ -436,33 +282,6 @@ log("Unknown message during authentication: type %d", type); break; } - -#ifdef HAVE_LOGIN_CAP - if (pw != NULL) { - lc = login_getpwclass(pw); - if (lc == NULL) - lc = login_getclassbyname(NULL, pw); - if (!auth_hostok(lc, from_host, from_ip)) { - log("Denied connection for %.200s from %.200s [%.200s].", - pw->pw_name, from_host, from_ip); - packet_disconnect("Sorry, you are not allowed to connect."); - } - if (!auth_timeok(lc, time(NULL))) { - log("LOGIN %.200s REFUSED (TIME) FROM %.200s", - pw->pw_name, from_host); - packet_disconnect("Logins not available right now."); - } - login_close(lc); - lc = NULL; - } -#endif /* HAVE_LOGIN_CAP */ -#ifdef LOGIN_ACCESS - if (pw != NULL && !login_access(pw->pw_name, from_host)) { - log("Denied connection for %.200s from %.200s [%.200s].", - pw->pw_name, from_host, from_ip); - packet_disconnect("Sorry, you are not allowed to connect."); - } -#endif /* LOGIN_ACCESS */ #ifdef BSD_AUTH if (authctxt->as) { auth_close(authctxt->as); @@ -473,24 +292,28 @@ fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); +#ifdef HAVE_CYGWIN + if (authenticated && + !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) { + packet_disconnect("Authentication rejected for uid %d.", + pw == NULL ? -1 : pw->pw_uid); + authenticated = 0; + } +#else /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(get_authname(type))) authenticated = 0; - - if (pw != NULL && pw->pw_uid == 0) - log("ROOT LOGIN as '%.100s' from %.100s", - pw->pw_name, - get_canonical_hostname(options.reverse_mapping_check)); - - /* Log before sending the reply */ - auth_log(authctxt, authenticated, get_authname(type), info); - +#endif #ifdef USE_PAM - if (authenticated && !do_pam_account(pw->pw_name, client_user)) + if (!use_privsep && authenticated && + !do_pam_account(pw->pw_name, client_user)) authenticated = 0; #endif + /* Log before sending the reply */ + auth_log(authctxt, authenticated, get_authname(type), info); + if (client_user != NULL) { xfree(client_user); client_user = NULL; @@ -499,8 +322,15 @@ if (authenticated) return; - if (authctxt->failures++ > AUTH_FAIL_MAX) + if (authctxt->failures++ > AUTH_FAIL_MAX) { +#ifdef WITH_AIXAUTHENTICATE + /* XXX: privsep */ + loginfailed(authctxt->user, + get_canonical_hostname(options.verify_reverse_mapping), + "ssh"); +#endif /* WITH_AIXAUTHENTICATE */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + } packet_start(SSH_SMSG_FAILURE); packet_send(); @@ -512,52 +342,59 @@ * Performs authentication of an incoming connection. Session key has already * been exchanged and encryption is enabled. */ -void -do_authentication() +Authctxt * +do_authentication(void) { Authctxt *authctxt; - struct passwd *pw; - int plen; u_int ulen; char *user, *style = NULL; /* Get the name of the user that we wish to log in as. */ - packet_read_expect(&plen, SSH_CMSG_USER); + packet_read_expect(SSH_CMSG_USER); /* Get the user name. */ user = packet_get_string(&ulen); - packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER); + packet_check_eom(); if ((style = strchr(user, ':')) != NULL) - *style++ = 0; + *style++ = '\0'; + +#ifdef KRB5 + /* XXX - SSH.com Kerberos v5 braindeath. */ + if ((datafellows & SSH_BUG_K5USER) && + options.kerberos_authentication) { + char *p; + if ((p = strchr(user, '@')) != NULL) + *p = '\0'; + } +#endif authctxt = authctxt_new(); authctxt->user = user; authctxt->style = style; /* Verify that the user is a valid user. */ - pw = getpwnam(user); - if (pw && allowed_user(pw)) { + if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) authctxt->valid = 1; - pw = pwcopy(pw); - } else { + else debug("do_authentication: illegal user %s", user); - pw = NULL; - } - authctxt->pw = pw; + + setproctitle("%s%s", authctxt->pw ? user : "unknown", + use_privsep ? " [net]" : ""); #ifdef USE_PAM - if (pw != NULL) - start_pam(pw); + PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user)); #endif - setproctitle("%s", pw ? user : "unknown"); /* * If we are not running as root, the user must have the same uid as - * the server. + * the server. (Unless you are running Windows) */ - if (getuid() != 0 && pw && pw->pw_uid != getuid()) +#ifndef HAVE_CYGWIN + if (!use_privsep && getuid() != 0 && authctxt->pw && + authctxt->pw->pw_uid != getuid()) packet_disconnect("Cannot change user when server not running as root."); +#endif /* * Loop until the user has been authenticated or the connection is @@ -570,6 +407,5 @@ packet_send(); packet_write_wait(); - /* Perform session preparation. */ - do_authenticated(authctxt); + return (authctxt); } Index: src/crypto/openssh/auth2-chall.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth2-chall.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 auth2-chall.c --- src/crypto/openssh/auth2-chall.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/auth2-chall.c 30 Jun 2002 11:37:57 -0000 @@ -1,5 +1,6 @@ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2001 Per Allansson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,91 +23,329 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: auth2-chall.c,v 1.4 2001/03/28 22:43:31 markus Exp $"); +RCSID("$OpenBSD: auth2-chall.c,v 1.19 2002/06/26 13:55:37 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/auth2-chall.c,v 1.6 2002/06/29 11:48:58 des Exp $"); #include "ssh2.h" #include "auth.h" +#include "buffer.h" #include "packet.h" #include "xmalloc.h" #include "dispatch.h" +#include "auth.h" #include "log.h" -void send_userauth_into_request(Authctxt *authctxt, char *challenge, int echo); -void input_userauth_info_response(int type, int plen, void *ctxt); +static int auth2_challenge_start(Authctxt *); +static int send_userauth_info_request(Authctxt *); +static void input_userauth_info_response(int, u_int32_t, void *); + +#ifdef BSD_AUTH +extern KbdintDevice bsdauth_device; +#else +#ifdef USE_PAM +extern KbdintDevice pam_device; +#endif +#ifdef SKEY +extern KbdintDevice skey_device; +#endif +#endif + +KbdintDevice *devices[] = { +#ifdef BSD_AUTH + &bsdauth_device, +#else +#ifdef USE_PAM + &pam_device, +#endif +#ifdef SKEY + &skey_device, +#endif +#endif + NULL +}; + +typedef struct KbdintAuthctxt KbdintAuthctxt; +struct KbdintAuthctxt +{ + char *devices; + void *ctxt; + KbdintDevice *device; + u_int nreq; +}; + +static KbdintAuthctxt * +kbdint_alloc(const char *devs) +{ + KbdintAuthctxt *kbdintctxt; + Buffer b; + int i; + + kbdintctxt = xmalloc(sizeof(KbdintAuthctxt)); + if (strcmp(devs, "") == 0) { + buffer_init(&b); + for (i = 0; devices[i]; i++) { + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, devices[i]->name, + strlen(devices[i]->name)); + } + buffer_append(&b, "\0", 1); + kbdintctxt->devices = xstrdup(buffer_ptr(&b)); + buffer_free(&b); + } else { + kbdintctxt->devices = xstrdup(devs); + } + debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); + kbdintctxt->ctxt = NULL; + kbdintctxt->device = NULL; + kbdintctxt->nreq = 0; + + return kbdintctxt; +} +static void +kbdint_reset_device(KbdintAuthctxt *kbdintctxt) +{ + if (kbdintctxt->ctxt) { + kbdintctxt->device->free_ctx(kbdintctxt->ctxt); + kbdintctxt->ctxt = NULL; + } + kbdintctxt->device = NULL; +} +static void +kbdint_free(KbdintAuthctxt *kbdintctxt) +{ + if (kbdintctxt->device) + kbdint_reset_device(kbdintctxt); + if (kbdintctxt->devices) { + xfree(kbdintctxt->devices); + kbdintctxt->devices = NULL; + } + xfree(kbdintctxt); +} +/* get next device */ +static int +kbdint_next_device(KbdintAuthctxt *kbdintctxt) +{ + size_t len; + char *t; + int i; + + if (kbdintctxt->device) + kbdint_reset_device(kbdintctxt); + do { + len = kbdintctxt->devices ? + strcspn(kbdintctxt->devices, ",") : 0; + + if (len == 0) + break; + for (i = 0; devices[i]; i++) + if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0) + kbdintctxt->device = devices[i]; + t = kbdintctxt->devices; + kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; + xfree(t); + debug2("kbdint_next_device: devices %s", kbdintctxt->devices ? + kbdintctxt->devices : ""); + } while (kbdintctxt->devices && !kbdintctxt->device); + + return kbdintctxt->device ? 1 : 0; +} /* - * try challenge-reponse, return -1 (= postponed) if we have to + * try challenge-response, set authctxt->postponed if we have to * wait for the response. */ int auth2_challenge(Authctxt *authctxt, char *devs) { - char *challenge; + debug("auth2_challenge: user=%s devs=%s", + authctxt->user ? authctxt->user : "", + devs ? devs : ""); - if (!authctxt->valid || authctxt->user == NULL) + if (authctxt->user == NULL || !devs) return 0; - if ((challenge = get_challenge(authctxt, devs)) == NULL) + if (authctxt->kbdintctxt == NULL) + authctxt->kbdintctxt = kbdint_alloc(devs); + return auth2_challenge_start(authctxt); +} + +/* unregister kbd-int callbacks and context */ +void +auth2_challenge_stop(Authctxt *authctxt) +{ + /* unregister callback */ + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + if (authctxt->kbdintctxt != NULL) { + kbdint_free(authctxt->kbdintctxt); + authctxt->kbdintctxt = NULL; + } +} + +/* side effect: sets authctxt->postponed if a reply was sent*/ +static int +auth2_challenge_start(Authctxt *authctxt) +{ + KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt; + + debug2("auth2_challenge_start: devices %s", + kbdintctxt->devices ? kbdintctxt->devices : ""); + + if (kbdint_next_device(kbdintctxt) == 0) { + auth2_challenge_stop(authctxt); + return 0; + } + debug("auth2_challenge_start: trying authentication method '%s'", + kbdintctxt->device->name); + + if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { + auth2_challenge_stop(authctxt); + return 0; + } + if (send_userauth_info_request(authctxt) == 0) { + auth2_challenge_stop(authctxt); return 0; - send_userauth_into_request(authctxt, challenge, 0); + } dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &input_userauth_info_response); + authctxt->postponed = 1; return 0; } -void -send_userauth_into_request(Authctxt *authctxt, char *challenge, int echo) +static int +send_userauth_info_request(Authctxt *authctxt) { - int nprompts = 1; + KbdintAuthctxt *kbdintctxt; + char *name, *instr, **prompts; + int i; + u_int *echo_on; + + kbdintctxt = authctxt->kbdintctxt; + if (kbdintctxt->device->query(kbdintctxt->ctxt, + &name, &instr, &kbdintctxt->nreq, &prompts, &echo_on)) + return 0; packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); - /* name, instruction and language are unused */ - packet_put_cstring(""); - packet_put_cstring(""); - packet_put_cstring(""); - packet_put_int(nprompts); - packet_put_cstring(challenge); - packet_put_char(echo); + packet_put_cstring(name); + packet_put_cstring(instr); + packet_put_cstring(""); /* language not used */ + packet_put_int(kbdintctxt->nreq); + for (i = 0; i < kbdintctxt->nreq; i++) { + packet_put_cstring(prompts[i]); + packet_put_char(echo_on[i]); + } packet_send(); packet_write_wait(); + + for (i = 0; i < kbdintctxt->nreq; i++) + xfree(prompts[i]); + xfree(prompts); + xfree(echo_on); + xfree(name); + xfree(instr); + return 1; } -void -input_userauth_info_response(int type, int plen, void *ctxt) +static void +input_userauth_info_response(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; - int authenticated = 0; - u_int nresp, rlen; - char *response, *method = "challenge-reponse"; + KbdintAuthctxt *kbdintctxt; + int i, authenticated = 0, res, len; + u_int nresp; + char **response = NULL, *method; if (authctxt == NULL) fatal("input_userauth_info_response: no authctxt"); + kbdintctxt = authctxt->kbdintctxt; + if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL) + fatal("input_userauth_info_response: no kbdintctxt"); + if (kbdintctxt->device == NULL) + fatal("input_userauth_info_response: no device"); authctxt->postponed = 0; /* reset */ nresp = packet_get_int(); - if (nresp == 1) { - response = packet_get_string(&rlen); - packet_done(); - if (strlen(response) == 0) { - /* - * if we received an empty response, resend challenge - * with echo enabled - */ - char *challenge = get_challenge(authctxt, NULL); - if (challenge != NULL) { - send_userauth_into_request(authctxt, - challenge, 1); - authctxt->postponed = 1; - } - } else if (authctxt->valid) { - authenticated = verify_response(authctxt, response); - memset(response, 'r', rlen); - } + if (nresp != kbdintctxt->nreq) + fatal("input_userauth_info_response: wrong number of replies"); + if (nresp > 100) + fatal("input_userauth_info_response: too many replies"); + if (nresp > 0) { + response = xmalloc(nresp * sizeof(char*)); + for (i = 0; i < nresp; i++) + response[i] = packet_get_string(NULL); + } + packet_check_eom(); + + if (authctxt->valid) { + res = kbdintctxt->device->respond(kbdintctxt->ctxt, + nresp, response); + } else { + res = -1; + } + + for (i = 0; i < nresp; i++) { + memset(response[i], 'r', strlen(response[i])); + xfree(response[i]); + } + if (response) xfree(response); + + switch (res) { + case 0: + /* Success! */ + authenticated = 1; + break; + case 1: + /* Authentication needs further interaction */ + if (send_userauth_info_request(authctxt) == 1) + authctxt->postponed = 1; + break; + default: + /* Failure! */ + break; } - /* unregister callback */ - if (!authctxt->postponed) - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + len = strlen("keyboard-interactive") + 2 + + strlen(kbdintctxt->device->name); + method = xmalloc(len); + snprintf(method, len, "keyboard-interactive/%s", + kbdintctxt->device->name); + + if (!authctxt->postponed) { + if (authenticated) { + auth2_challenge_stop(authctxt); + } else { + /* start next device */ + /* may set authctxt->postponed */ + auth2_challenge_start(authctxt); + } + } userauth_finish(authctxt, authenticated, method); + xfree(method); +} + +void +privsep_challenge_enable(void) +{ +#ifdef BSD_AUTH + extern KbdintDevice mm_bsdauth_device; +#endif +#ifdef USE_PAM + extern KbdintDevice mm_pam_device; +#endif +#ifdef SKEY + extern KbdintDevice mm_skey_device; +#endif + int n = 0; + +#ifdef BSD_AUTH + devices[n++] = &mm_bsdauth_device; +#else +#ifdef USE_PAM + devices[n++] = &mm_pam_device; +#endif +#ifdef SKEY + devices[n++] = &mm_skey_device; +#endif +#endif } Index: src/crypto/openssh/auth2-hostbased.c =================================================================== RCS file: src/crypto/openssh/auth2-hostbased.c diff -N src/crypto/openssh/auth2-hostbased.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-hostbased.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2000 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: auth2-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); + +#include "ssh2.h" +#include "xmalloc.h" +#include "packet.h" +#include "buffer.h" +#include "log.h" +#include "servconf.h" +#include "compat.h" +#include "bufaux.h" +#include "auth.h" +#include "key.h" +#include "canohost.h" +#include "monitor_wrap.h" +#include "pathnames.h" + +/* import */ +extern ServerOptions options; +extern u_char *session_id2; +extern int session_id2_len; + +static int +userauth_hostbased(Authctxt *authctxt) +{ + Buffer b; + Key *key = NULL; + char *pkalg, *cuser, *chost, *service; + u_char *pkblob, *sig; + u_int alen, blen, slen; + int pktype; + int authenticated = 0; + + if (!authctxt->valid) { + debug2("userauth_hostbased: disabled because of invalid user"); + return 0; + } + pkalg = packet_get_string(&alen); + pkblob = packet_get_string(&blen); + chost = packet_get_string(NULL); + cuser = packet_get_string(NULL); + sig = packet_get_string(&slen); + + debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", + cuser, chost, pkalg, slen); +#ifdef DEBUG_PK + debug("signature:"); + buffer_init(&b); + buffer_append(&b, sig, slen); + buffer_dump(&b); + buffer_free(&b); +#endif + pktype = key_type_from_name(pkalg); + if (pktype == KEY_UNSPEC) { + /* this is perfectly legal */ + log("userauth_hostbased: unsupported " + "public key algorithm: %s", pkalg); + goto done; + } + key = key_from_blob(pkblob, blen); + if (key == NULL) { + error("userauth_hostbased: cannot decode key: %s", pkalg); + goto done; + } + if (key->type != pktype) { + error("userauth_hostbased: type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); + goto done; + } + service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : + authctxt->service; + buffer_init(&b); + buffer_put_string(&b, session_id2, session_id2_len); + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); + buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, service); + buffer_put_cstring(&b, "hostbased"); + buffer_put_string(&b, pkalg, alen); + buffer_put_string(&b, pkblob, blen); + buffer_put_cstring(&b, chost); + buffer_put_cstring(&b, cuser); +#ifdef DEBUG_PK + buffer_dump(&b); +#endif + /* test for allowed key and correct signature */ + authenticated = 0; + if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && + PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) + authenticated = 1; + + buffer_clear(&b); +done: + debug2("userauth_hostbased: authenticated %d", authenticated); + if (key != NULL) + key_free(key); + xfree(pkalg); + xfree(pkblob); + xfree(cuser); + xfree(chost); + xfree(sig); + return authenticated; +} + +/* return 1 if given hostkey is allowed */ +int +hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, + Key *key) +{ + const char *resolvedname, *ipaddr, *lookup; + HostStatus host_status; + int len; + + resolvedname = get_canonical_hostname(options.verify_reverse_mapping); + ipaddr = get_remote_ipaddr(); + + debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", + chost, resolvedname, ipaddr); + + if (options.hostbased_uses_name_from_packet_only) { + if (auth_rhosts2(pw, cuser, chost, chost) == 0) + return 0; + lookup = chost; + } else { + if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { + debug2("stripping trailing dot from chost %s", chost); + chost[len - 1] = '\0'; + } + if (strcasecmp(resolvedname, chost) != 0) + log("userauth_hostbased mismatch: " + "client sends %s, but we resolve %s to %s", + chost, ipaddr, resolvedname); + if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) + return 0; + lookup = resolvedname; + } + debug2("userauth_hostbased: access allowed by auth_rhosts2"); + + host_status = check_key_in_hostfiles(pw, key, lookup, + _PATH_SSH_SYSTEM_HOSTFILE, + options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); + + /* backward compat if no key has been found. */ + if (host_status == HOST_NEW) + host_status = check_key_in_hostfiles(pw, key, lookup, + _PATH_SSH_SYSTEM_HOSTFILE2, + options.ignore_user_known_hosts ? NULL : + _PATH_SSH_USER_HOSTFILE2); + + return (host_status == HOST_OK); +} + +Authmethod method_hostbased = { + "hostbased", + userauth_hostbased, + &options.hostbased_authentication +}; Index: src/crypto/openssh/auth2-kbdint.c =================================================================== RCS file: src/crypto/openssh/auth2-kbdint.c diff -N src/crypto/openssh/auth2-kbdint.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-kbdint.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2000 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: auth2-kbdint.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); + +#include "packet.h" +#include "auth.h" +#include "log.h" +#include "servconf.h" +#include "xmalloc.h" + +/* import */ +extern ServerOptions options; + +static int +userauth_kbdint(Authctxt *authctxt) +{ + int authenticated = 0; + char *lang, *devs; + + lang = packet_get_string(NULL); + devs = packet_get_string(NULL); + packet_check_eom(); + + debug("keyboard-interactive devs %s", devs); + + if (options.challenge_response_authentication) + authenticated = auth2_challenge(authctxt, devs); + +#ifdef USE_PAM + if (authenticated == 0 && options.pam_authentication_via_kbd_int) + authenticated = auth2_pam(authctxt); +#endif + xfree(devs); + xfree(lang); +#ifdef HAVE_CYGWIN + if (check_nt_auth(0, authctxt->pw) == 0) + return(0); +#endif + return authenticated; +} + +Authmethod method_kbdint = { + "keyboard-interactive", + userauth_kbdint, + &options.kbd_interactive_authentication +}; Index: src/crypto/openssh/auth2-none.c =================================================================== RCS file: src/crypto/openssh/auth2-none.c diff -N src/crypto/openssh/auth2-none.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-none.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2000 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: auth2-none.c,v 1.3 2002/06/19 00:27:55 deraadt Exp $"); + +#include "auth.h" +#include "xmalloc.h" +#include "packet.h" +#include "log.h" +#include "servconf.h" +#include "atomicio.h" +#include "compat.h" +#include "ssh2.h" +#include "monitor_wrap.h" + +/* import */ +extern ServerOptions options; + +/* "none" is allowed only one time */ +static int none_enabled = 1; + +char * +auth2_read_banner(void) +{ + struct stat st; + char *banner = NULL; + off_t len, n; + int fd; + + if ((fd = open(options.banner, O_RDONLY)) == -1) + return (NULL); + if (fstat(fd, &st) == -1) { + close(fd); + return (NULL); + } + len = st.st_size; + banner = xmalloc(len + 1); + n = atomicio(read, fd, banner, len); + close(fd); + + if (n != len) { + free(banner); + return (NULL); + } + banner[n] = '\0'; + + return (banner); +} + +static void +userauth_banner(void) +{ + char *banner = NULL; + + if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) + return; + + if ((banner = PRIVSEP(auth2_read_banner())) == NULL) + goto done; + + packet_start(SSH2_MSG_USERAUTH_BANNER); + packet_put_cstring(banner); + packet_put_cstring(""); /* language, unused */ + packet_send(); + debug("userauth_banner: sent"); +done: + if (banner) + xfree(banner); +} + +static int +userauth_none(Authctxt *authctxt) +{ + none_enabled = 0; + packet_check_eom(); + userauth_banner(); +#ifdef HAVE_CYGWIN + if (check_nt_auth(1, authctxt->pw) == 0) + return(0); +#endif + return (authctxt->valid ? PRIVSEP(auth_password(authctxt, "")) : 0); +} + +Authmethod method_none = { + "none", + userauth_none, + &none_enabled +}; Index: src/crypto/openssh/auth2-pam-freebsd.c =================================================================== RCS file: src/crypto/openssh/auth2-pam-freebsd.c diff -N src/crypto/openssh/auth2-pam-freebsd.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-pam-freebsd.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,372 @@ +/*- + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by ThinkSec AS and + * NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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. + */ + +#include "includes.h" +RCSID("$FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.1 2002/06/29 10:56:23 des Exp $"); + +#ifdef USE_PAM +#include + +#include "auth.h" +#include "log.h" +#include "monitor_wrap.h" +#include "packet.h" +#include "ssh2.h" +#include "xmalloc.h" + +struct pam_ctxt { + char *pam_user; + pid_t pam_pid; + int pam_sock; + int pam_done; +}; + +static void pam_free_ctx(void *); + +/* + * Send message to parent or child. + */ +static int +pam_send(struct pam_ctxt *ctxt, char *fmt, ...) +{ + va_list ap; + char *mstr; + size_t len; + int r; + + va_start(ap, fmt); + len = vasprintf(&mstr, fmt, ap); + va_end(ap); + if (mstr == NULL) + exit(1); + if (ctxt->pam_pid != 0) + debug2("to child: %s", mstr); + r = send(ctxt->pam_sock, mstr, len + 1, MSG_EOR); + free(mstr); + return (r); +} + +/* + * Peek at first byte of next message. + */ +static int +pam_peek(struct pam_ctxt *ctxt) +{ + char ch; + + if (recv(ctxt->pam_sock, &ch, 1, MSG_PEEK) < 1) + return (-1); + return (ch); +} + +/* + * Receive a message from parent or child. + */ +static char * +pam_receive(struct pam_ctxt *ctxt) +{ + char *buf; + size_t len; + ssize_t rlen; + + len = 64; + buf = NULL; + do { + len *= 2; + buf = xrealloc(buf, len); + rlen = recv(ctxt->pam_sock, buf, len, MSG_PEEK); + if (rlen < 1) { + xfree(buf); + return (NULL); + } + } while (rlen == len); + if (recv(ctxt->pam_sock, buf, len, 0) != rlen) { + xfree(buf); + return (NULL); + } + if (ctxt->pam_pid != 0) + debug2("from child: %s", buf); + return (buf); +} + +/* + * Conversation function for child process. + */ +static int +pam_child_conv(int n, + const struct pam_message **msg, + struct pam_response **resp, + void *data) +{ + struct pam_ctxt *ctxt; + int i; + + ctxt = data; + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return (PAM_CONV_ERR); + if ((*resp = calloc(n, sizeof **resp)) == NULL) + return (PAM_BUF_ERR); + for (i = 0; i < n; ++i) { + resp[i]->resp_retcode = 0; + resp[i]->resp = NULL; + switch (msg[i]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + pam_send(ctxt, "p%s", msg[i]->msg); + resp[i]->resp = pam_receive(ctxt); + break; + case PAM_PROMPT_ECHO_ON: + pam_send(ctxt, "P%s", msg[i]->msg); + resp[i]->resp = pam_receive(ctxt); + break; + case PAM_ERROR_MSG: + pam_send(ctxt, "e%s", msg[i]->msg); + break; + case PAM_TEXT_INFO: + pam_send(ctxt, "i%s", msg[i]->msg); + break; + default: + goto fail; + } + } + return (PAM_SUCCESS); + fail: + while (i) + free(resp[--i]); + free(*resp); + *resp = NULL; + return (PAM_CONV_ERR); +} + +/* + * Child process. + */ +static void * +pam_child(struct pam_ctxt *ctxt) +{ + struct pam_conv pam_conv = { pam_child_conv, ctxt }; + pam_handle_t *pamh; + int pam_err; + + pam_err = pam_start("sshd", ctxt->pam_user, &pam_conv, &pamh); + if (pam_err != PAM_SUCCESS) + goto auth_fail; + pam_err = pam_authenticate(pamh, 0); + if (pam_err != PAM_SUCCESS) + goto auth_fail; + pam_err = pam_acct_mgmt(pamh, 0); + if (pam_err != PAM_SUCCESS) + goto auth_fail; + pam_send(ctxt, "=OK"); + pam_end(pamh, pam_err); + exit(0); + auth_fail: + pam_send(ctxt, "!%s", pam_strerror(pamh, pam_err)); + pam_end(pamh, pam_err); + exit(0); +} + +static void * +pam_init_ctx(Authctxt *authctxt) +{ + struct pam_ctxt *ctxt; + int socks[2]; + int i; + + ctxt = xmalloc(sizeof *ctxt); + ctxt->pam_user = xstrdup(authctxt->user); + ctxt->pam_done = 0; + if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, socks) == -1) { + error("%s: failed create sockets: %s", + __func__, strerror(errno)); + xfree(ctxt); + return (NULL); + } + if ((ctxt->pam_pid = fork()) == -1) { + error("%s: failed to fork auth-pam child: %s", + __func__, strerror(errno)); + close(socks[0]); + close(socks[1]); + xfree(ctxt); + return (NULL); + } + if (ctxt->pam_pid == 0) { + /* close everything except our end of the pipe */ + ctxt->pam_sock = socks[1]; + for (i = 0; i < getdtablesize(); ++i) + if (i != ctxt->pam_sock) + close(i); + pam_child(ctxt); + /* not reached */ + exit(1); + } + ctxt->pam_sock = socks[0]; + close(socks[1]); + return (ctxt); +} + +static int +pam_query(void *ctx, char **name, char **info, + u_int *num, char ***prompts, u_int **echo_on) +{ + struct pam_ctxt *ctxt = ctx; + size_t plen; + char *msg; + + *name = xstrdup(""); + *info = xstrdup(""); + *prompts = xmalloc(sizeof(char *)); + **prompts = NULL; + plen = 0; + *echo_on = xmalloc(sizeof(u_int)); + while ((msg = pam_receive(ctxt)) != NULL) { + switch (*msg) { + case 'P': + case 'p': + *num = 1; + **prompts = xrealloc(**prompts, plen + strlen(msg)); + plen += sprintf(**prompts + plen, "%s", msg + 1); + **echo_on = (*msg == 'P'); + xfree(msg); + return (0); + case 'e': + case 'i': + /* accumulate messages */ + **prompts = xrealloc(**prompts, plen + strlen(msg)); + plen += sprintf(**prompts + plen, "%s", msg + 1); + break; + case '=': + case '!': + if (**prompts != NULL) { + /* drain any accumulated messages */ +#if 0 /* not compatible with privsep */ + packet_start(SSH2_MSG_USERAUTH_BANNER); + packet_put_cstring(**prompts); + packet_put_cstring(""); + packet_send(); + packet_write_wait(); +#endif + xfree(**prompts); + **prompts = NULL; + } + if (*msg == '=') { + *num = 0; + **echo_on = 0; + ctxt->pam_done = 1; + xfree(msg); + return (0); + } + error("%s", msg + 1); + default: + *num = 0; + **echo_on = 0; + xfree(msg); + ctxt->pam_done = -1; + return (-1); + } + xfree(msg); + } + return (-1); +} + +static int +pam_respond(void *ctx, u_int num, char **resp) +{ + struct pam_ctxt *ctxt = ctx; + char *msg; + + debug2(__func__); + switch (ctxt->pam_done) { + case 1: + return (0); + case 0: + break; + default: + return (-1); + } + if (num != 1) { + error("expected one response, got %u", num); + return (-1); + } + pam_send(ctxt, "%s", *resp); + switch (pam_peek(ctxt)) { + case 'P': + case 'p': + case 'e': + case 'i': + return (1); + case '=': + msg = pam_receive(ctxt); + xfree(msg); + ctxt->pam_done = 1; + return (0); + default: + msg = pam_receive(ctxt); + if (*msg == '!') + error("%s", msg + 1); + xfree(msg); + ctxt->pam_done = -1; + return (-1); + } +} + +static void +pam_free_ctx(void *ctxtp) +{ + struct pam_ctxt *ctxt = ctxtp; + int status; + + close(ctxt->pam_sock); + kill(ctxt->pam_pid, SIGHUP); + waitpid(ctxt->pam_pid, &status, 0); + xfree(ctxt->pam_user); + xfree(ctxt); +} + +KbdintDevice pam_device = { + "pam", + pam_init_ctx, + pam_query, + pam_respond, + pam_free_ctx +}; + +KbdintDevice mm_pam_device = { + "pam", + mm_pam_init_ctx, + mm_pam_query, + mm_pam_respond, + mm_pam_free_ctx +}; + +#endif /* USE_PAM */ Index: src/crypto/openssh/auth2-pam.c =================================================================== RCS file: src/crypto/openssh/auth2-pam.c diff -N src/crypto/openssh/auth2-pam.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-pam.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,168 @@ +#include "includes.h" +RCSID("$Id$"); +RCSID("$FreeBSD: src/crypto/openssh/auth2-pam.c,v 1.4 2002/06/29 11:48:58 des Exp $"); + +#ifdef USE_PAM +#include + +#include "ssh.h" +#include "ssh2.h" +#include "auth.h" +#include "auth-pam.h" +#include "packet.h" +#include "xmalloc.h" +#include "dispatch.h" +#include "log.h" + +static int do_pam_conversation_kbd_int(int num_msg, + const struct pam_message **msg, struct pam_response **resp, + void *appdata_ptr); +void input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt); + +struct { + int finished, num_received, num_expected; + int *prompts; + struct pam_response *responses; +} context_pam2 = {0, 0, 0, NULL}; + +static struct pam_conv conv2 = { + do_pam_conversation_kbd_int, + NULL, +}; + +int +auth2_pam(Authctxt *authctxt) +{ + int retval = -1; + + if (authctxt->user == NULL) + fatal("auth2_pam: internal error: no user"); + + conv2.appdata_ptr = authctxt; + do_pam_set_conv(&conv2); + + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, + &input_userauth_info_response_pam); + retval = (do_pam_authenticate(0) == PAM_SUCCESS); + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + + return retval; +} + +static int +do_pam_conversation_kbd_int(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + int i, j, done; + char *text; + + context_pam2.finished = 0; + context_pam2.num_received = 0; + context_pam2.num_expected = 0; + context_pam2.prompts = xmalloc(sizeof(int) * num_msg); + context_pam2.responses = xmalloc(sizeof(struct pam_response) * num_msg); + memset(context_pam2.responses, 0, sizeof(struct pam_response) * num_msg); + + text = NULL; + for (i = 0, context_pam2.num_expected = 0; i < num_msg; i++) { + int style = PAM_MSG_MEMBER(msg, i, msg_style); + switch (style) { + case PAM_PROMPT_ECHO_ON: + case PAM_PROMPT_ECHO_OFF: + context_pam2.num_expected++; + break; + case PAM_TEXT_INFO: + case PAM_ERROR_MSG: + default: + /* Capture all these messages to be sent at once */ + message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); + break; + } + } + + if (context_pam2.num_expected == 0) + return PAM_SUCCESS; + + packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); + packet_put_cstring(""); /* Name */ + packet_put_cstring(""); /* Instructions */ + packet_put_cstring(""); /* Language */ + packet_put_int(context_pam2.num_expected); + + for (i = 0, j = 0; i < num_msg; i++) { + int style = PAM_MSG_MEMBER(msg, i, msg_style); + + /* Skip messages which don't need a reply */ + if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF) + continue; + + context_pam2.prompts[j++] = i; + if (text) { + message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); + packet_put_cstring(text); + text = NULL; + } else + packet_put_cstring(PAM_MSG_MEMBER(msg, i, msg)); + packet_put_char(style == PAM_PROMPT_ECHO_ON); + } + packet_send(); + packet_write_wait(); + + /* + * Grabbing control of execution and spinning until we get what + * we want is probably rude, but it seems to work properly, and + * the client *should* be in lock-step with us, so the loop should + * only be traversed once. + */ + while(context_pam2.finished == 0) { + done = 1; + dispatch_run(DISPATCH_BLOCK, &done, appdata_ptr); + if(context_pam2.finished == 0) + debug("extra packet during conversation"); + } + + if(context_pam2.num_received == context_pam2.num_expected) { + *resp = context_pam2.responses; + return PAM_SUCCESS; + } else + return PAM_CONV_ERR; +} + +void +input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt) +{ + Authctxt *authctxt = ctxt; + unsigned int nresp = 0, rlen = 0, i = 0; + char *resp; + + if (authctxt == NULL) + fatal("input_userauth_info_response_pam: no authentication context"); + + nresp = packet_get_int(); /* Number of responses. */ + debug("got %d responses", nresp); + + + if (nresp != context_pam2.num_expected) + fatal("%s: Received incorrect number of responses " + "(expected %u, received %u)", __func__, nresp, + context_pam2.num_expected); + + if (nresp > 100) + fatal("%s: too many replies", __func__); + + for (i = 0; i < nresp; i++) { + int j = context_pam2.prompts[i]; + + resp = packet_get_string(&rlen); + context_pam2.responses[j].resp_retcode = PAM_SUCCESS; + context_pam2.responses[j].resp = xstrdup(resp); + xfree(resp); + context_pam2.num_received++; + } + + context_pam2.finished = 1; + + packet_check_eom(); +} + +#endif Index: src/crypto/openssh/auth2-pam.h =================================================================== RCS file: src/crypto/openssh/auth2-pam.h diff -N src/crypto/openssh/auth2-pam.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-pam.h 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,8 @@ +/* $Id$ */ + +#include "includes.h" +#ifdef USE_PAM + +int auth2_pam(Authctxt *authctxt); + +#endif /* USE_PAM */ Index: src/crypto/openssh/auth2-passwd.c =================================================================== RCS file: src/crypto/openssh/auth2-passwd.c diff -N src/crypto/openssh/auth2-passwd.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-passwd.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: auth2-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); + +#include "xmalloc.h" +#include "packet.h" +#include "log.h" +#include "auth.h" +#include "monitor_wrap.h" +#include "servconf.h" + +/* import */ +extern ServerOptions options; + +static int +userauth_passwd(Authctxt *authctxt) +{ + char *password; + int authenticated = 0; + int change; + u_int len; + change = packet_get_char(); + if (change) + log("password change not supported"); + password = packet_get_string(&len); + packet_check_eom(); + if (authctxt->valid && +#ifdef HAVE_CYGWIN + check_nt_auth(1, authctxt->pw) && +#endif + PRIVSEP(auth_password(authctxt, password)) == 1) + authenticated = 1; + memset(password, 0, len); + xfree(password); + return authenticated; +} + +Authmethod method_passwd = { + "password", + userauth_passwd, + &options.password_authentication +}; Index: src/crypto/openssh/auth2-pubkey.c =================================================================== RCS file: src/crypto/openssh/auth2-pubkey.c diff -N src/crypto/openssh/auth2-pubkey.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/auth2-pubkey.c 30 Jun 2002 11:37:57 -0000 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2000 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $"); + +#include "ssh2.h" +#include "xmalloc.h" +#include "packet.h" +#include "buffer.h" +#include "log.h" +#include "servconf.h" +#include "compat.h" +#include "bufaux.h" +#include "auth.h" +#include "key.h" +#include "pathnames.h" +#include "uidswap.h" +#include "auth-options.h" +#include "canohost.h" +#include "monitor_wrap.h" + +/* import */ +extern ServerOptions options; +extern u_char *session_id2; +extern int session_id2_len; + +static int +userauth_pubkey(Authctxt *authctxt) +{ + Buffer b; + Key *key = NULL; + char *pkalg; + u_char *pkblob, *sig; + u_int alen, blen, slen; + int have_sig, pktype; + int authenticated = 0; + + if (!authctxt->valid) { + debug2("userauth_pubkey: disabled because of invalid user"); + return 0; + } + have_sig = packet_get_char(); + if (datafellows & SSH_BUG_PKAUTH) { + debug2("userauth_pubkey: SSH_BUG_PKAUTH"); + /* no explicit pkalg given */ + pkblob = packet_get_string(&blen); + buffer_init(&b); + buffer_append(&b, pkblob, blen); + /* so we have to extract the pkalg from the pkblob */ + pkalg = buffer_get_string(&b, &alen); + buffer_free(&b); + } else { + pkalg = packet_get_string(&alen); + pkblob = packet_get_string(&blen); + } + pktype = key_type_from_name(pkalg); + if (pktype == KEY_UNSPEC) { + /* this is perfectly legal */ + log("userauth_pubkey: unsupported public key algorithm: %s", + pkalg); + goto done; + } + key = key_from_blob(pkblob, blen); + if (key == NULL) { + error("userauth_pubkey: cannot decode key: %s", pkalg); + goto done; + } + if (key->type != pktype) { + error("userauth_pubkey: type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); + goto done; + } + if (have_sig) { + sig = packet_get_string(&slen); + packet_check_eom(); + buffer_init(&b); + if (datafellows & SSH_OLD_SESSIONID) { + buffer_append(&b, session_id2, session_id2_len); + } else { + buffer_put_string(&b, session_id2, session_id2_len); + } + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); + buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, + datafellows & SSH_BUG_PKSERVICE ? + "ssh-userauth" : + authctxt->service); + if (datafellows & SSH_BUG_PKAUTH) { + buffer_put_char(&b, have_sig); + } else { + buffer_put_cstring(&b, "publickey"); + buffer_put_char(&b, have_sig); + buffer_put_cstring(&b, pkalg); + } + buffer_put_string(&b, pkblob, blen); +#ifdef DEBUG_PK + buffer_dump(&b); +#endif + /* test for correct signature */ + authenticated = 0; + if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && + PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) + authenticated = 1; + buffer_clear(&b); + xfree(sig); + } else { + debug("test whether pkalg/pkblob are acceptable"); + packet_check_eom(); + + /* XXX fake reply and always send PK_OK ? */ + /* + * XXX this allows testing whether a user is allowed + * to login: if you happen to have a valid pubkey this + * message is sent. the message is NEVER sent at all + * if a user is not allowed to login. is this an + * issue? -markus + */ + if (PRIVSEP(user_key_allowed(authctxt->pw, key))) { + packet_start(SSH2_MSG_USERAUTH_PK_OK); + packet_put_string(pkalg, alen); + packet_put_string(pkblob, blen); + packet_send(); + packet_write_wait(); + authctxt->postponed = 1; + } + } + if (authenticated != 1) + auth_clear_options(); +done: + debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); + if (key != NULL) + key_free(key); + xfree(pkalg); + xfree(pkblob); +#ifdef HAVE_CYGWIN + if (check_nt_auth(0, authctxt->pw) == 0) + return(0); +#endif + return authenticated; +} + +/* return 1 if user allows given key */ +static int +user_key_allowed2(struct passwd *pw, Key *key, char *file) +{ + char line[8192]; + int found_key = 0; + FILE *f; + u_long linenum = 0; + struct stat st; + Key *found; + char *fp; + + if (pw == NULL) + return 0; + + /* Temporarily use the user's uid. */ + temporarily_use_uid(pw); + + debug("trying public key file %s", file); + + /* Fail quietly if file does not exist */ + if (stat(file, &st) < 0) { + /* Restore the privileged uid. */ + restore_uid(); + return 0; + } + /* Open the file containing the authorized keys. */ + f = fopen(file, "r"); + if (!f) { + /* Restore the privileged uid. */ + restore_uid(); + return 0; + } + if (options.strict_modes && + secure_filename(f, file, pw, line, sizeof(line)) != 0) { + fclose(f); + log("Authentication refused: %s", line); + restore_uid(); + return 0; + } + + found_key = 0; + found = key_new(key->type); + + while (fgets(line, sizeof(line), f)) { + char *cp, *options = NULL; + linenum++; + /* Skip leading whitespace, empty and comment lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + + if (key_read(found, &cp) != 1) { + /* no key? check if there are options for this key */ + int quoted = 0; + debug2("user_key_allowed: check options: '%s'", cp); + options = cp; + for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { + if (*cp == '\\' && cp[1] == '"') + cp++; /* Skip both */ + else if (*cp == '"') + quoted = !quoted; + } + /* Skip remaining whitespace. */ + for (; *cp == ' ' || *cp == '\t'; cp++) + ; + if (key_read(found, &cp) != 1) { + debug2("user_key_allowed: advance: '%s'", cp); + /* still no key? advance to next line*/ + continue; + } + } + if (key_equal(found, key) && + auth_parse_options(pw, options, file, linenum) == 1) { + found_key = 1; + debug("matching key found: file %s, line %lu", + file, linenum); + fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(found), fp); + xfree(fp); + break; + } + } + restore_uid(); + fclose(f); + key_free(found); + if (!found_key) + debug2("key not found"); + return found_key; +} + +/* check whether given key is in .ssh/authorized_keys* */ +int +user_key_allowed(struct passwd *pw, Key *key) +{ + int success; + char *file; + + file = authorized_keys_file(pw); + success = user_key_allowed2(pw, key, file); + xfree(file); + if (success) + return success; + + /* try suffix "2" for backward compat, too */ + file = authorized_keys_file2(pw); + success = user_key_allowed2(pw, key, file); + xfree(file); + return success; +} + +Authmethod method_pubkey = { + "publickey", + userauth_pubkey, + &options.pubkey_authentication +}; Index: src/crypto/openssh/auth2.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/auth2.c,v retrieving revision 1.2.2.7 diff -u -u -r1.2.2.7 auth2.c --- src/crypto/openssh/auth2.c 28 Sep 2001 01:33:33 -0000 1.2.2.7 +++ src/crypto/openssh/auth2.c 30 Jun 2002 11:37:58 -0000 @@ -23,140 +23,89 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.56 2001/04/19 00:05:11 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/auth2.c,v 1.2.2.7 2001/09/28 01:33:33 green Exp $"); - -#include +RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/auth2.c,v 1.17 2002/06/29 10:57:13 des Exp $"); #include "ssh2.h" #include "xmalloc.h" -#include "rsa.h" -#include "sshpty.h" #include "packet.h" -#include "buffer.h" #include "log.h" #include "servconf.h" #include "compat.h" -#include "channels.h" -#include "bufaux.h" #include "auth.h" -#include "session.h" #include "dispatch.h" -#include "key.h" -#include "cipher.h" -#include "kex.h" #include "pathnames.h" -#include "uidswap.h" -#include "auth-options.h" -#include "misc.h" -#include "hostfile.h" -#include "canohost.h" -#include "tildexpand.h" - -#ifdef HAVE_LOGIN_CAP -#include -#endif /* HAVE_LOGIN_CAP */ +#include "monitor_wrap.h" /* import */ extern ServerOptions options; extern u_char *session_id2; extern int session_id2_len; -static Authctxt *x_authctxt = NULL; -static int one = 1; +Authctxt *x_authctxt = NULL; + +/* methods */ -typedef struct Authmethod Authmethod; -struct Authmethod { - char *name; - int (*userauth)(Authctxt *authctxt); - int *enabled; +extern Authmethod method_none; +extern Authmethod method_pubkey; +extern Authmethod method_passwd; +extern Authmethod method_kbdint; +extern Authmethod method_hostbased; + +Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + &method_passwd, + &method_kbdint, + &method_hostbased, + NULL }; /* protocol */ -void input_service_request(int type, int plen, void *ctxt); -void input_userauth_request(int type, int plen, void *ctxt); -void protocol_error(int type, int plen, void *ctxt); +static void input_service_request(int, u_int32_t, void *); +static void input_userauth_request(int, u_int32_t, void *); /* helper */ -Authmethod *authmethod_lookup(const char *name); -char *authmethods_get(void); -int user_key_allowed(struct passwd *pw, Key *key); -int -hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - Key *key); - -/* auth */ -void userauth_banner(void); -void userauth_reply(Authctxt *authctxt, int authenticated); -int userauth_none(Authctxt *authctxt); -int userauth_passwd(Authctxt *authctxt); -int userauth_pubkey(Authctxt *authctxt); -int userauth_hostbased(Authctxt *authctxt); -int userauth_kbdint(Authctxt *authctxt); - -Authmethod authmethods[] = { - {"none", - userauth_none, - &one}, - {"publickey", - userauth_pubkey, - &options.pubkey_authentication}, - {"password", - userauth_passwd, - &options.password_authentication}, - {"keyboard-interactive", - userauth_kbdint, - &options.kbd_interactive_authentication}, - {"hostbased", - userauth_hostbased, - &options.hostbased_authentication}, - {NULL, NULL, NULL} -}; +static Authmethod *authmethod_lookup(const char *); +static char *authmethods_get(void); +int user_key_allowed(struct passwd *, Key *); +int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); /* * loop until authctxt->success == TRUE */ -void -do_authentication2() +Authctxt * +do_authentication2(void) { Authctxt *authctxt = authctxt_new(); x_authctxt = authctxt; /*XXX*/ -#if defined(KRB4) || defined(KRB5) - /* turn off kerberos, not supported by SSH2 */ - options.kerberos_authentication = 0; -#endif - /* challenge-reponse is implemented via keyboard interactive */ - if (options.challenge_reponse_authentication) + /* challenge-response is implemented via keyboard interactive */ + if (options.challenge_response_authentication) + options.kbd_interactive_authentication = 1; + if (options.pam_authentication_via_kbd_int) options.kbd_interactive_authentication = 1; + if (use_privsep) + options.pam_authentication_via_kbd_int = 0; - dispatch_init(&protocol_error); + dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); - do_authenticated(authctxt); -} -void -protocol_error(int type, int plen, void *ctxt) -{ - log("auth: protocol error: type %d plen %d", type, plen); - packet_start(SSH2_MSG_UNIMPLEMENTED); - packet_put_int(0); - packet_send(); - packet_write_wait(); + return (authctxt); } -void -input_service_request(int type, int plen, void *ctxt) +static void +input_service_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; u_int len; int accept = 0; char *service = packet_get_string(&len); - packet_done(); + packet_check_eom(); if (authctxt == NULL) fatal("input_service_request: no authctxt"); @@ -182,8 +131,8 @@ xfree(service); } -void -input_userauth_request(int type, int plen, void *ctxt) +static void +input_userauth_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Authmethod *m = NULL; @@ -191,13 +140,11 @@ int authenticated = 0; #ifdef HAVE_LOGIN_CAP login_cap_t *lc; -#endif /* HAVE_LOGIN_CAP */ -#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS) const char *from_host, *from_ip; - from_host = get_canonical_hostname(options.reverse_mapping_check); - from_ip = get_remote_ipaddr(); -#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */ + from_host = get_canonical_hostname(options.verify_reverse_mapping); + from_ip = get_remote_ipaddr(); +#endif if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); @@ -213,68 +160,56 @@ if (authctxt->attempt++ == 0) { /* setup auth context */ - struct passwd *pw = NULL; - pw = getpwnam(user); - if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) { - authctxt->pw = pwcopy(pw); + authctxt->pw = PRIVSEP(getpwnamallow(user)); + if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; debug2("input_userauth_request: setting up authctxt for %s", user); #ifdef USE_PAM - start_pam(pw); + PRIVSEP(start_pam(authctxt->pw->pw_name)); #endif } else { log("input_userauth_request: illegal user %s", user); - authctxt->pw = NULL; +#ifdef USE_PAM + PRIVSEP(start_pam("NOUSER")); +#endif } - setproctitle("%s", pw ? user : "unknown"); + setproctitle("%s%s", authctxt->pw ? user : "unknown", + use_privsep ? " [net]" : ""); authctxt->user = xstrdup(user); authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; /* currently unused */ - } else if (authctxt->valid) { - if (strcmp(user, authctxt->user) != 0 || - strcmp(service, authctxt->service) != 0) { - log("input_userauth_request: mismatch: (%s,%s)!=(%s,%s)", - user, service, authctxt->user, authctxt->service); - authctxt->valid = 0; - } + authctxt->style = style ? xstrdup(style) : NULL; + if (use_privsep) + mm_inform_authserv(service, style); + } else if (strcmp(user, authctxt->user) != 0 || + strcmp(service, authctxt->service) != 0) { + packet_disconnect("Change of username or service not allowed: " + "(%s,%s) -> (%s,%s)", + authctxt->user, authctxt->service, user, service); } #ifdef HAVE_LOGIN_CAP - if (authctxt->pw != NULL) { - lc = login_getpwclass(authctxt->pw); - if (lc == NULL) - lc = login_getclassbyname(NULL, authctxt->pw); - if (!auth_hostok(lc, from_host, from_ip)) { - log("Denied connection for %.200s from %.200s [%.200s].", - authctxt->pw->pw_name, from_host, from_ip); - packet_disconnect("Sorry, you are not allowed to connect."); - } - if (!auth_timeok(lc, time(NULL))) { - log("LOGIN %.200s REFUSED (TIME) FROM %.200s", - authctxt->pw->pw_name, from_host); - packet_disconnect("Logins not available right now."); - } - login_close(lc); - lc = NULL; - } + if (authctxt->pw != NULL) { + lc = login_getpwclass(authctxt->pw); + if (lc == NULL) + lc = login_getclassbyname(NULL, authctxt->pw); + if (!auth_hostok(lc, from_host, from_ip)) { + log("Denied connection for %.200s from %.200s [%.200s].", + authctxt->pw->pw_name, from_host, from_ip); + packet_disconnect("Sorry, you are not allowed to connect."); + } + if (!auth_timeok(lc, time(NULL))) { + log("LOGIN %.200s REFUSED (TIME) FROM %.200s", + authctxt->pw->pw_name, from_host); + packet_disconnect("Logins not available right now."); + } + login_close(lc); + lc = NULL; + } #endif /* HAVE_LOGIN_CAP */ -#ifdef LOGIN_ACCESS - if (authctxt->pw != NULL && - !login_access(authctxt->pw->pw_name, from_host)) { - log("Denied connection for %.200s from %.200s [%.200s].", - authctxt->pw->pw_name, from_host, from_ip); - packet_disconnect("Sorry, you are not allowed to connect."); - } -#endif /* LOGIN_ACCESS */ + /* reset state */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error); + auth2_challenge_stop(authctxt); authctxt->postponed = 0; -#ifdef BSD_AUTH - if (authctxt->as) { - auth_close(authctxt->as); - authctxt->as = NULL; - } -#endif /* try to authenticate user */ m = authmethod_lookup(method); @@ -282,10 +217,6 @@ debug2("input_userauth_request: try method %s", method); authenticated = m->userauth(authctxt); } -#ifdef USE_PAM - if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL)) - authenticated = 0; -#endif /* USE_PAM */ userauth_finish(authctxt, authenticated, method); xfree(service); @@ -296,6 +227,8 @@ void userauth_finish(Authctxt *authctxt, int authenticated, char *method) { + char *methods; + if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); @@ -305,61 +238,37 @@ !auth_root_allowed(method)) authenticated = 0; +#ifdef USE_PAM + if (!use_privsep && authenticated && authctxt->user && + !do_pam_account(authctxt->user, NULL)) + authenticated = 0; +#endif /* USE_PAM */ + /* Log before sending the reply */ auth_log(authctxt, authenticated, method, " ssh2"); - if (!authctxt->postponed) - userauth_reply(authctxt, authenticated); -} - -void -userauth_banner(void) -{ - struct stat st; - char *banner = NULL; - off_t len, n; - int fd; - - if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) + if (authctxt->postponed) return; - if ((fd = open(options.banner, O_RDONLY)) < 0) - return; - if (fstat(fd, &st) < 0) - goto done; - len = st.st_size; - banner = xmalloc(len + 1); - if ((n = read(fd, banner, len)) < 0) - goto done; - banner[n] = '\0'; - packet_start(SSH2_MSG_USERAUTH_BANNER); - packet_put_cstring(banner); - packet_put_cstring(""); /* language, unused */ - packet_send(); - debug("userauth_banner: sent"); -done: - if (banner) - xfree(banner); - close(fd); - return; -} - -void -userauth_reply(Authctxt *authctxt, int authenticated) -{ - char *methods; /* XXX todo: check if multiple auth methods are needed */ if (authenticated == 1) { /* turn off userauth */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error); + dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); /* now we can break out */ authctxt->success = 1; } else { - if (authctxt->failures++ > AUTH_FAIL_MAX) + if (authctxt->failures++ > AUTH_FAIL_MAX) { +#ifdef WITH_AIXAUTHENTICATE + /* XXX: privsep */ + loginfailed(authctxt->user, + get_canonical_hostname(options.verify_reverse_mapping), + "ssh"); +#endif /* WITH_AIXAUTHENTICATE */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + } methods = authmethods_get(); packet_start(SSH2_MSG_USERAUTH_FAILURE); packet_put_cstring(methods); @@ -370,245 +279,6 @@ } } -int -userauth_none(Authctxt *authctxt) -{ - /* disable method "none", only allowed one time */ - Authmethod *m = authmethod_lookup("none"); - if (m != NULL) - m->enabled = NULL; - packet_done(); - userauth_banner(); -#ifdef USE_PAM - return authctxt->valid ? auth_pam_password(authctxt, "") : 0; -#else /* !USE_PAM */ - return authctxt->valid ? auth_password(authctxt, "") : 0; -#endif /* USE_PAM */ -} - -int -userauth_passwd(Authctxt *authctxt) -{ - char *password; - int authenticated = 0; - int change; - u_int len; - change = packet_get_char(); - if (change) - log("password change not supported"); - password = packet_get_string(&len); - packet_done(); - if (authctxt->valid && -#ifdef USE_PAM - auth_pam_password(authctxt, password) == 1 -#else - auth_password(authctxt, password) == 1 -#endif - ) - authenticated = 1; - memset(password, 0, len); - xfree(password); - return authenticated; -} - -int -userauth_kbdint(Authctxt *authctxt) -{ - int authenticated = 0; - char *lang = NULL; - char *devs = NULL; - - lang = packet_get_string(NULL); - devs = packet_get_string(NULL); - packet_done(); - - debug("keyboard-interactive language %s devs %s", lang, devs); - - if (options.challenge_reponse_authentication) - authenticated = auth2_challenge(authctxt, devs); - - xfree(lang); - xfree(devs); - return authenticated; -} - -int -userauth_pubkey(Authctxt *authctxt) -{ - Buffer b; - Key *key; - char *pkalg, *pkblob, *sig; - u_int alen, blen, slen; - int have_sig, pktype; - int authenticated = 0; - - if (!authctxt->valid) { - debug2("userauth_pubkey: disabled because of invalid user"); - return 0; - } - have_sig = packet_get_char(); - if (datafellows & SSH_BUG_PKAUTH) { - debug2("userauth_pubkey: SSH_BUG_PKAUTH"); - /* no explicit pkalg given */ - pkblob = packet_get_string(&blen); - buffer_init(&b); - buffer_append(&b, pkblob, blen); - /* so we have to extract the pkalg from the pkblob */ - pkalg = buffer_get_string(&b, &alen); - buffer_free(&b); - } else { - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - } - pktype = key_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) { - /* this is perfectly legal */ - log("userauth_pubkey: unsupported public key algorithm: %s", pkalg); - xfree(pkalg); - xfree(pkblob); - return 0; - } - key = key_from_blob(pkblob, blen); - if (key != NULL) { - if (have_sig) { - sig = packet_get_string(&slen); - packet_done(); - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); - } else { - buffer_put_string(&b, session_id2, session_id2_len); - } - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); - } else { - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, pkalg); - } - buffer_put_string(&b, pkblob, blen); -#ifdef DEBUG_PK - buffer_dump(&b); -#endif - /* test for correct signature */ - if (user_key_allowed(authctxt->pw, key) && - key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) - authenticated = 1; - buffer_clear(&b); - xfree(sig); - } else { - debug("test whether pkalg/pkblob are acceptable"); - packet_done(); - - /* XXX fake reply and always send PK_OK ? */ - /* - * XXX this allows testing whether a user is allowed - * to login: if you happen to have a valid pubkey this - * message is sent. the message is NEVER sent at all - * if a user is not allowed to login. is this an - * issue? -markus - */ - if (user_key_allowed(authctxt->pw, key)) { - packet_start(SSH2_MSG_USERAUTH_PK_OK); - packet_put_string(pkalg, alen); - packet_put_string(pkblob, blen); - packet_send(); - packet_write_wait(); - authctxt->postponed = 1; - } - } - if (authenticated != 1) - auth_clear_options(); - key_free(key); - } - debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); - xfree(pkalg); - xfree(pkblob); - return authenticated; -} - -int -userauth_hostbased(Authctxt *authctxt) -{ - Buffer b; - Key *key; - char *pkalg, *pkblob, *sig, *cuser, *chost, *service; - u_int alen, blen, slen; - int pktype; - int authenticated = 0; - - if (!authctxt->valid) { - debug2("userauth_hostbased: disabled because of invalid user"); - return 0; - } - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - chost = packet_get_string(NULL); - cuser = packet_get_string(NULL); - sig = packet_get_string(&slen); - - debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", - cuser, chost, pkalg, slen); -#ifdef DEBUG_PK - debug("signature:"); - buffer_init(&b); - buffer_append(&b, sig, slen); - buffer_dump(&b); - buffer_free(&b); -#endif - pktype = key_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) { - /* this is perfectly legal */ - log("userauth_hostbased: unsupported " - "public key algorithm: %s", pkalg); - goto done; - } - key = key_from_blob(pkblob, blen); - if (key == NULL) { - debug("userauth_hostbased: cannot decode key: %s", pkalg); - goto done; - } - service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : - authctxt->service; - buffer_init(&b); - buffer_put_string(&b, session_id2, session_id2_len); - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, "hostbased"); - buffer_put_string(&b, pkalg, alen); - buffer_put_string(&b, pkblob, blen); - buffer_put_cstring(&b, chost); - buffer_put_cstring(&b, cuser); -#ifdef DEBUG_PK - buffer_dump(&b); -#endif - /* test for allowed key and correct signature */ - if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) && - key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) - authenticated = 1; - - buffer_clear(&b); - key_free(key); - -done: - debug2("userauth_hostbased: authenticated %d", authenticated); - xfree(pkalg); - xfree(pkblob); - xfree(cuser); - xfree(chost); - xfree(sig); - return authenticated; -} - /* get current user */ struct passwd* @@ -619,236 +289,43 @@ #define DELIM "," -char * +static char * authmethods_get(void) { - Authmethod *method = NULL; - u_int size = 0; + Buffer b; char *list; + int i; - for (method = authmethods; method->name != NULL; method++) { - if (strcmp(method->name, "none") == 0) - continue; - if (method->enabled != NULL && *(method->enabled) != 0) { - if (size != 0) - size += strlen(DELIM); - size += strlen(method->name); - } - } - size++; /* trailing '\0' */ - list = xmalloc(size); - list[0] = '\0'; - - for (method = authmethods; method->name != NULL; method++) { - if (strcmp(method->name, "none") == 0) + buffer_init(&b); + for (i = 0; authmethods[i] != NULL; i++) { + if (strcmp(authmethods[i]->name, "none") == 0) continue; - if (method->enabled != NULL && *(method->enabled) != 0) { - if (list[0] != '\0') - strlcat(list, DELIM, size); - strlcat(list, method->name, size); + if (authmethods[i]->enabled != NULL && + *(authmethods[i]->enabled) != 0) { + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, authmethods[i]->name, + strlen(authmethods[i]->name)); } } + buffer_append(&b, "\0", 1); + list = xstrdup(buffer_ptr(&b)); + buffer_free(&b); return list; } -Authmethod * +static Authmethod * authmethod_lookup(const char *name) { - Authmethod *method = NULL; + int i; + if (name != NULL) - for (method = authmethods; method->name != NULL; method++) - if (method->enabled != NULL && - *(method->enabled) != 0 && - strcmp(name, method->name) == 0) - return method; - debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); + for (i = 0; authmethods[i] != NULL; i++) + if (authmethods[i]->enabled != NULL && + *(authmethods[i]->enabled) != 0 && + strcmp(name, authmethods[i]->name) == 0) + return authmethods[i]; + debug2("Unrecognized authentication method name: %s", + name ? name : "NULL"); return NULL; -} - -/* return 1 if user allows given key */ -int -user_key_allowed(struct passwd *pw, Key *key) -{ - char line[8192], file[MAXPATHLEN]; - int found_key = 0; - FILE *f; - u_long linenum = 0; - struct stat st; - Key *found; - - if (pw == NULL) - return 0; - - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - - /* The authorized keys. */ - snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir, - _PATH_SSH_USER_PERMITTED_KEYS2); - - /* Fail quietly if file does not exist */ - if (stat(file, &st) < 0) { - /* Restore the privileged uid. */ - restore_uid(); - return 0; - } - /* Open the file containing the authorized keys. */ - f = fopen(file, "r"); - if (!f) { - /* Restore the privileged uid. */ - restore_uid(); - return 0; - } - if (options.strict_modes) { - int fail = 0; - char buf[1024]; - /* Check open file in order to avoid open/stat races */ - if (fstat(fileno(f), &st) < 0 || - (st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0) { - snprintf(buf, sizeof buf, - "%s authentication refused for %.100s: " - "bad ownership or modes for '%s'.", - key_type(key), pw->pw_name, file); - fail = 1; - } else { - /* Check path to _PATH_SSH_USER_PERMITTED_KEYS */ - int i; - static const char *check[] = { - "", _PATH_SSH_USER_DIR, NULL - }; - for (i = 0; check[i]; i++) { - snprintf(line, sizeof line, "%.500s/%.100s", - pw->pw_dir, check[i]); - if (stat(line, &st) < 0 || - (st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0) { - snprintf(buf, sizeof buf, - "%s authentication refused for %.100s: " - "bad ownership or modes for '%s'.", - key_type(key), pw->pw_name, line); - fail = 1; - break; - } - } - } - if (fail) { - fclose(f); - log("%s", buf); - restore_uid(); - return 0; - } - } - found_key = 0; - found = key_new(key->type); - - while (fgets(line, sizeof(line), f)) { - char *cp, *options = NULL; - linenum++; - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; - - if (key_read(found, &cp) == -1) { - /* no key? check if there are options for this key */ - int quoted = 0; - debug2("user_key_allowed: check options: '%s'", cp); - options = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - /* Skip remaining whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - if (key_read(found, &cp) == -1) { - debug2("user_key_allowed: advance: '%s'", cp); - /* still no key? advance to next line*/ - continue; - } - } - if (key_equal(found, key) && - auth_parse_options(pw, options, file, linenum) == 1) { - found_key = 1; - debug("matching key found: file %s, line %ld", - file, linenum); - break; - } - } - restore_uid(); - fclose(f); - key_free(found); - if (!found_key) - debug2("key not found"); - return found_key; -} - -/* return 1 if given hostkey is allowed */ -int -hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - Key *key) -{ - Key *found; - const char *resolvedname, *ipaddr, *lookup; - struct stat st; - char *user_hostfile; - int host_status, len; - - resolvedname = get_canonical_hostname(options.reverse_mapping_check); - ipaddr = get_remote_ipaddr(); - - debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", - chost, resolvedname, ipaddr); - - if (options.hostbased_uses_name_from_packet_only) { - if (auth_rhosts2(pw, cuser, chost, chost) == 0) - return 0; - lookup = chost; - } else { - if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { - debug2("stripping trailing dot from chost %s", chost); - chost[len - 1] = '\0'; - } - if (strcasecmp(resolvedname, chost) != 0) - log("userauth_hostbased mismatch: " - "client sends %s, but we resolve %s to %s", - chost, ipaddr, resolvedname); - if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) - return 0; - lookup = resolvedname; - } - debug2("userauth_hostbased: access allowed by auth_rhosts2"); - - /* XXX this is copied from auth-rh-rsa.c and should be shared */ - found = key_new(key->type); - host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE2, lookup, - key, found, NULL); - - if (host_status != HOST_OK && !options.ignore_user_known_hosts) { - user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE2, - pw->pw_uid); - if (options.strict_modes && - (stat(user_hostfile, &st) == 0) && - ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { - log("Hostbased authentication refused for %.100s: " - "bad owner or modes for %.200s", - pw->pw_name, user_hostfile); - } else { - temporarily_use_uid(pw); - host_status = check_host_in_hostfile(user_hostfile, - lookup, key, found, NULL); - restore_uid(); - } - xfree(user_hostfile); - } - key_free(found); - - debug2("userauth_hostbased: key %s for %s", host_status == HOST_OK ? - "ok" : "not found", lookup); - return (host_status == HOST_OK); } Index: src/crypto/openssh/authfd.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/authfd.c,v retrieving revision 1.2.2.5 diff -u -u -r1.2.2.5 authfd.c --- src/crypto/openssh/authfd.c 28 Sep 2001 01:33:33 -0000 1.2.2.5 +++ src/crypto/openssh/authfd.c 30 Jun 2002 11:37:58 -0000 @@ -35,8 +35,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfd.c,v 1.39 2001/04/05 10:42:48 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/authfd.c,v 1.2.2.5 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: authfd.c,v 1.56 2002/06/25 16:22:42 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/authfd.c,v 1.12 2002/06/29 11:48:58 des Exp $"); #include @@ -59,7 +59,8 @@ /* macro to check for "agent failure" message */ #define agent_failed(x) \ - ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE)) + ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \ + (x == SSH2_AGENT_FAILURE)) /* Returns the number of the authentication fd, or -1 if there is none. */ @@ -67,7 +68,7 @@ ssh_get_authentication_socket(void) { const char *authsocket; - int sock, len; + int sock; struct sockaddr_un sunaddr; authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); @@ -76,8 +77,6 @@ sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); - len = SUN_LEN(&sunaddr)+1; - sunaddr.sun_len = len; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) @@ -88,14 +87,14 @@ close(sock); return -1; } - if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) { + if (connect(sock, (struct sockaddr *) &sunaddr, sizeof sunaddr) < 0) { close(sock); return -1; } return sock; } -int +static int ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) { int l, len; @@ -146,7 +145,7 @@ error("Error reading response from authentication socket."); return 0; } - buffer_append(reply, (char *) buf, l); + buffer_append(reply, buf, l); len -= l; } return 1; @@ -209,6 +208,26 @@ xfree(auth); } +/* Lock/unlock agent */ +int +ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password) +{ + int type; + Buffer msg; + + buffer_init(&msg); + buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK); + buffer_put_cstring(&msg, password); + + if (ssh_request_reply(auth, &msg, &msg) == 0) { + buffer_free(&msg); + return 0; + } + type = buffer_get_char(&msg); + buffer_free(&msg); + return decode_reply(type); +} + /* * Returns the first authentication identity held by the agent. */ @@ -219,7 +238,7 @@ int type, code1 = 0, code2 = 0; Buffer request; - switch(version){ + switch (version) { case 1: code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; @@ -288,7 +307,7 @@ * Get the next entry from the packet. These will abort with a fatal * error if the packet is too short or contains corrupt data. */ - switch(version){ + switch (version) { case 1: key = key_new(KEY_RSA1); bits = buffer_get_int(&auth->identities); @@ -346,7 +365,7 @@ buffer_put_bignum(&buffer, key->rsa->e); buffer_put_bignum(&buffer, key->rsa->n); buffer_put_bignum(&buffer, challenge); - buffer_append(&buffer, (char *) session_id, 16); + buffer_append(&buffer, session_id, 16); buffer_put_int(&buffer, response_type); if (ssh_request_reply(auth, &buffer, &buffer) == 0) { @@ -376,8 +395,8 @@ int ssh_agent_sign(AuthenticationConnection *auth, Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen) + u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { extern int datafellows; Buffer msg; @@ -418,11 +437,9 @@ /* Encode key for a message to the agent. */ -void +static void ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) { - buffer_clear(b); - buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY); buffer_put_int(b, BN_num_bits(key->n)); buffer_put_bignum(b, key->n); buffer_put_bignum(b, key->e); @@ -431,16 +448,14 @@ buffer_put_bignum(b, key->iqmp); /* ssh key->u */ buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ - buffer_put_string(b, comment, strlen(comment)); + buffer_put_cstring(b, comment); } -void +static void ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) { - buffer_clear(b); - buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY); buffer_put_cstring(b, key_ssh_name(key)); - switch(key->type){ + switch (key->type) { case KEY_RSA: buffer_put_bignum2(b, key->rsa->n); buffer_put_bignum2(b, key->rsa->e); @@ -466,19 +481,28 @@ */ int -ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) +ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, + const char *comment, u_int life) { Buffer msg; - int type; + int type, constrained = (life != 0); buffer_init(&msg); switch (key->type) { case KEY_RSA1: + type = constrained ? + SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : + SSH_AGENTC_ADD_RSA_IDENTITY; + buffer_put_char(&msg, type); ssh_encode_identity_rsa1(&msg, key->rsa, comment); break; case KEY_RSA: case KEY_DSA: + type = constrained ? + SSH2_AGENTC_ADD_ID_CONSTRAINED : + SSH2_AGENTC_ADD_IDENTITY; + buffer_put_char(&msg, type); ssh_encode_identity_ssh2(&msg, key, comment); break; default: @@ -486,6 +510,12 @@ return 0; break; } + if (constrained) { + if (life != 0) { + buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); + buffer_put_int(&msg, life); + } + } if (ssh_request_reply(auth, &msg, &msg) == 0) { buffer_free(&msg); return 0; @@ -495,6 +525,12 @@ return decode_reply(type); } +int +ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) +{ + return ssh_add_identity_constrained(auth, key, comment, 0); +} + /* * Removes an identity from the authentication server. This call is not * meant to be used by normal applications. @@ -533,6 +569,26 @@ return decode_reply(type); } +int +ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin) +{ + Buffer msg; + int type; + + buffer_init(&msg); + buffer_put_char(&msg, add ? SSH_AGENTC_ADD_SMARTCARD_KEY : + SSH_AGENTC_REMOVE_SMARTCARD_KEY); + buffer_put_cstring(&msg, reader_id); + buffer_put_cstring(&msg, pin); + if (ssh_request_reply(auth, &msg, &msg) == 0) { + buffer_free(&msg); + return 0; + } + type = buffer_get_char(&msg); + buffer_free(&msg); + return decode_reply(type); +} + /* * Removes all identities from the agent. This call is not meant to be used * by normal applications. @@ -565,6 +621,7 @@ switch (type) { case SSH_AGENT_FAILURE: case SSH_COM_AGENT2_FAILURE: + case SSH2_AGENT_FAILURE: log("SSH_AGENT_FAILURE"); return 0; case SSH_AGENT_SUCCESS: Index: src/crypto/openssh/authfd.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/authfd.h,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 authfd.h --- src/crypto/openssh/authfd.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/authfd.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: authfd.h,v 1.30 2002/06/19 00:27:55 deraadt Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: authfd.h,v 1.16 2000/12/20 19:37:21 markus Exp $"); */ - #ifndef AUTHFD_H #define AUTHFD_H @@ -38,101 +38,55 @@ #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 +/* smartcard */ +#define SSH_AGENTC_ADD_SMARTCARD_KEY 20 +#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 + +/* lock/unlock the agent */ +#define SSH_AGENTC_LOCK 22 +#define SSH_AGENTC_UNLOCK 23 + +/* add key with constraints */ +#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 +#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 + +#define SSH_AGENT_CONSTRAIN_LIFETIME 1 + +/* extended failure messages */ +#define SSH2_AGENT_FAILURE 30 + /* additional error code for ssh.com's ssh-agent2 */ -#define SSH_COM_AGENT2_FAILURE 102 +#define SSH_COM_AGENT2_FAILURE 102 #define SSH_AGENT_OLD_SIGNATURE 0x01 - typedef struct { - int fd; - Buffer identities; - int howmany; -} AuthenticationConnection; - -/* Returns the number of the authentication fd, or -1 if there is none. */ -int ssh_get_authentication_socket(void); + int fd; + Buffer identities; + int howmany; +} AuthenticationConnection; -/* - * This should be called for any descriptor returned by - * ssh_get_authentication_socket(). Depending on the way the descriptor was - * obtained, this may close the descriptor. - */ -void ssh_close_authentication_socket(int authfd); +int ssh_get_authentication_socket(void); +void ssh_close_authentication_socket(int); -/* - * 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(void); +void ssh_close_authentication_connection(AuthenticationConnection *); +int ssh_get_num_identities(AuthenticationConnection *, int); +Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); +Key *ssh_get_next_identity(AuthenticationConnection *, char **, int); +int ssh_add_identity(AuthenticationConnection *, Key *, const char *); +int ssh_add_identity_constrained(AuthenticationConnection *, Key *, const char *, u_int); +int ssh_remove_identity(AuthenticationConnection *, Key *); +int ssh_remove_all_identities(AuthenticationConnection *, int); +int ssh_lock_agent(AuthenticationConnection *, int, const char *); +int ssh_update_card(AuthenticationConnection *, int, const char *, const char *); -/* - * Closes the connection to the authentication agent and frees any associated - * memory. - */ -void ssh_close_authentication_connection(AuthenticationConnection *auth); - -/* - * Returns the number authentication identity held by the agent. - */ -int ssh_get_num_identities(AuthenticationConnection *auth, int version); - -/* - * Returns the first authentication identity held by the agent or NULL if - * no identies are available. Caller must free comment and key. - * Note that you cannot mix calls with different versions. - */ -Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version); - -/* - * 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 NULL if there are no more identities. The caller - * must free key and comment after a successful return. - */ -Key *ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version); - -/* - * 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, - Key *key, BIGNUM * challenge, - u_char session_id[16], - u_int response_type, - u_char response[16]); +ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], + u_int, u_char[16]); -/* Requests the agent to sign data using key */ int -ssh_agent_sign(AuthenticationConnection *auth, - Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen); - -/* - * 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 *auth, Key *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 *auth, Key *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 *auth, int version); +ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *, + u_int); #endif /* AUTHFD_H */ Index: src/crypto/openssh/authfile.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/authfile.c,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 authfile.c --- src/crypto/openssh/authfile.c 28 Sep 2001 01:33:33 -0000 1.2.2.4 +++ src/crypto/openssh/authfile.c 30 Jun 2002 11:37:58 -0000 @@ -36,8 +36,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfile.c,v 1.32 2001/04/18 23:44:51 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/authfile.c,v 1.2.2.4 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: authfile.c,v 1.50 2002/06/24 14:55:38 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/authfile.c,v 1.12 2002/06/29 11:48:58 des Exp $"); #include #include @@ -51,6 +51,7 @@ #include "ssh.h" #include "log.h" #include "authfile.h" +#include "rsa.h" /* Version identification string for SSH v1 identity files. */ static const char authfile_id_string[] = @@ -63,13 +64,13 @@ * passphrase. */ -int +static int key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, const char *comment) { Buffer buffer, encrypted; - char buf[100], *cp; - int fd, i; + u_char buf[100], *cp; + int fd, i, cipher_num; CipherContext ciphercontext; Cipher *cipher; u_int32_t rand; @@ -78,11 +79,9 @@ * 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 = cipher_by_number(SSH_CIPHER_NONE); - else - cipher = cipher_by_number(SSH_AUTHFILE_CIPHER); - if (cipher == NULL) + cipher_num = (strcmp(passphrase, "") == 0) ? + SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER; + if ((cipher = cipher_by_number(cipher_num)) == NULL) fatal("save_private_key_rsa: bad cipher"); /* This buffer is used to built the secret part of the private key. */ @@ -119,21 +118,23 @@ buffer_put_char(&encrypted, 0); /* Store cipher type. */ - buffer_put_char(&encrypted, cipher->number); + buffer_put_char(&encrypted, cipher_num); buffer_put_int(&encrypted, 0); /* For future extension */ /* Store public key. This will be in plain text. */ buffer_put_int(&encrypted, BN_num_bits(key->rsa->n)); buffer_put_bignum(&encrypted, key->rsa->n); buffer_put_bignum(&encrypted, key->rsa->e); - buffer_put_string(&encrypted, comment, strlen(comment)); + buffer_put_cstring(&encrypted, comment); /* Allocate space for the private part of the key in the buffer. */ - buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); + cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - cipher_set_key_string(&ciphercontext, cipher, passphrase); - cipher_encrypt(&ciphercontext, (u_char *) cp, - (u_char *) buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_set_key_string(&ciphercontext, cipher, passphrase, + CIPHER_ENCRYPT); + cipher_crypt(&ciphercontext, cp, + buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_cleanup(&ciphercontext); memset(&ciphercontext, 0, sizeof(ciphercontext)); /* Destroy temporary data. */ @@ -148,7 +149,7 @@ if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) != buffer_len(&encrypted)) { error("write to key file %s failed: %s", filename, - strerror(errno)); + strerror(errno)); buffer_free(&encrypted); close(fd); unlink(filename); @@ -160,7 +161,7 @@ } /* save SSH v2 key in OpenSSL PEM format */ -int +static int key_save_private_pem(Key *key, const char *filename, const char *_passphrase, const char *comment) { @@ -168,8 +169,8 @@ int fd; int success = 0; int len = strlen(_passphrase); - char *passphrase = (len > 0) ? (char *)_passphrase : NULL; - EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; + u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; + const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; if (len > 0 && len <= 4) { error("passphrase too short: have %d bytes, need > 4", len); @@ -227,7 +228,7 @@ * otherwise. */ -Key * +static Key * key_load_public_rsa1(int fd, const char *filename, char **commentp) { Buffer buffer; @@ -240,7 +241,7 @@ lseek(fd, (off_t) 0, SEEK_SET); buffer_init(&buffer); - buffer_append_space(&buffer, &cp, len); + cp = buffer_append_space(&buffer, len); if (read(fd, cp, (size_t) len) != (size_t) len) { debug("Read from key file %.200s failed: %.100s", filename, @@ -251,7 +252,7 @@ /* Check that it is at least big enough to contain the ID string. */ if (len < sizeof(authfile_id_string)) { - debug3("No RSA1 key file %.200s.", filename); + debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); return NULL; } @@ -261,7 +262,7 @@ */ for (i = 0; i < sizeof(authfile_id_string); i++) if (buffer_get_char(&buffer) != authfile_id_string[i]) { - debug3("No RSA1 key file %.200s.", filename); + debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); return NULL; } @@ -270,7 +271,7 @@ (void) buffer_get_int(&buffer); /* reserved */ /* Read the public key from the buffer. */ - buffer_get_int(&buffer); + (void) buffer_get_int(&buffer); pub = key_new(KEY_RSA1); buffer_get_bignum(&buffer, pub->rsa->n); buffer_get_bignum(&buffer, pub->rsa->e); @@ -307,25 +308,23 @@ * Assumes we are called under uid of the owner of the file. */ -Key * +static Key * key_load_private_rsa1(int fd, const char *filename, const char *passphrase, char **commentp) { int i, check1, check2, cipher_type; off_t len; Buffer buffer, decrypted; - char *cp; + u_char *cp; CipherContext ciphercontext; Cipher *cipher; - BN_CTX *ctx; - BIGNUM *aux; Key *prv = NULL; len = lseek(fd, (off_t) 0, SEEK_END); lseek(fd, (off_t) 0, SEEK_SET); buffer_init(&buffer); - buffer_append_space(&buffer, &cp, len); + cp = buffer_append_space(&buffer, len); if (read(fd, cp, (size_t) len) != (size_t) len) { debug("Read from key file %.200s failed: %.100s", filename, @@ -337,7 +336,7 @@ /* Check that it is at least big enough to contain the ID string. */ if (len < sizeof(authfile_id_string)) { - debug3("No RSA1 key file %.200s.", filename); + debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); close(fd); return NULL; @@ -348,7 +347,7 @@ */ for (i = 0; i < sizeof(authfile_id_string); i++) if (buffer_get_char(&buffer) != authfile_id_string[i]) { - debug3("No RSA1 key file %.200s.", filename); + debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); close(fd); return NULL; @@ -359,7 +358,7 @@ (void) buffer_get_int(&buffer); /* Reserved data. */ /* Read the public key from the buffer. */ - buffer_get_int(&buffer); + (void) buffer_get_int(&buffer); prv = key_new_private(KEY_RSA1); buffer_get_bignum(&buffer, prv->rsa->n); @@ -379,12 +378,14 @@ } /* Initialize space for decrypted data. */ buffer_init(&decrypted); - buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); + cp = buffer_append_space(&decrypted, buffer_len(&buffer)); /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ - cipher_set_key_string(&ciphercontext, cipher, passphrase); - cipher_decrypt(&ciphercontext, (u_char *) cp, - (u_char *) buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_set_key_string(&ciphercontext, cipher, passphrase, + CIPHER_DECRYPT); + cipher_crypt(&ciphercontext, cp, + buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_cleanup(&ciphercontext); memset(&ciphercontext, 0, sizeof(ciphercontext)); buffer_free(&buffer); @@ -407,17 +408,7 @@ buffer_get_bignum(&decrypted, prv->rsa->p); /* q */ /* calculate p-1 and q-1 */ - ctx = BN_CTX_new(); - aux = BN_new(); - - BN_sub(aux, prv->rsa->q, BN_value_one()); - BN_mod(prv->rsa->dmq1, prv->rsa->d, aux, ctx); - - BN_sub(aux, prv->rsa->p, BN_value_one()); - BN_mod(prv->rsa->dmp1, prv->rsa->d, aux, ctx); - - BN_clear_free(aux); - BN_CTX_free(ctx); + rsa_generate_additional_parameters(prv->rsa); buffer_free(&decrypted); close(fd); @@ -451,7 +442,7 @@ debug("PEM_read_PrivateKey failed"); (void)ERR_get_error(); } else if (pk->type == EVP_PKEY_RSA && - (type == KEY_UNSPEC||type==KEY_RSA)) { + (type == KEY_UNSPEC||type==KEY_RSA)) { prv = key_new(KEY_UNSPEC); prv->rsa = EVP_PKEY_get1_RSA(pk); prv->type = KEY_RSA; @@ -460,7 +451,7 @@ RSA_print_fp(stderr, prv->rsa, 8); #endif } else if (pk->type == EVP_PKEY_DSA && - (type == KEY_UNSPEC||type==KEY_DSA)) { + (type == KEY_UNSPEC||type==KEY_DSA)) { prv = key_new(KEY_UNSPEC); prv->dsa = EVP_PKEY_get1_DSA(pk); prv->type = KEY_DSA; @@ -482,20 +473,26 @@ return prv; } -int +static int key_perm_ok(int fd, const char *filename) { struct stat st; - /* check owner and modes */ - if (fstat(fd, &st) < 0 || - (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) || - (st.st_mode & 077) != 0) { - close(fd); + if (fstat(fd, &st) < 0) + return 0; + /* + * if a key owned by the user is accessed, then we check the + * permissions of the file. if the key owned by a different user, + * then we don't care. + */ +#ifdef HAVE_CYGWIN + if (check_ntsec(filename)) +#endif + if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("Bad ownership or mode(0%3.3o) for '%s'.", + error("Permissions 0%3.3o for '%s' are too open.", st.st_mode & 0777, filename); error("It is recommended that your private key files are NOT accessible by others."); error("This private key will be ignored."); @@ -541,7 +538,7 @@ key_load_private(const char *filename, const char *passphrase, char **commentp) { - Key *pub; + Key *pub, *prv; int fd; fd = open(filename, O_RDONLY); @@ -556,16 +553,20 @@ lseek(fd, (off_t) 0, SEEK_SET); /* rewind */ if (pub == NULL) { /* closes fd */ - return key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL); + prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL); + /* use the filename as a comment for PEM */ + if (commentp && prv) + *commentp = xstrdup(filename); } else { /* it's a SSH v1 key if the public key part is readable */ key_free(pub); /* closes fd */ - return key_load_private_rsa1(fd, filename, passphrase, NULL); + prv = key_load_private_rsa1(fd, filename, passphrase, NULL); } + return prv; } -int +static int key_try_load_public(Key *k, const char *filename, char **commentp) { FILE *f; @@ -577,7 +578,7 @@ while (fgets(line, sizeof(line), f)) { line[sizeof(line)-1] = '\0'; cp = line; - switch(*cp){ + switch (*cp) { case '#': case '\n': case '\0': Index: src/crypto/openssh/authfile.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/authfile.h,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 authfile.h --- src/crypto/openssh/authfile.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/authfile.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: authfile.h,v 1.10 2002/05/23 19:24:30 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,27 +12,14 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* $OpenBSD: authfile.h,v 1.6 2001/03/26 08:07:08 markus Exp $ */ - #ifndef AUTHFILE_H #define AUTHFILE_H -int -key_save_private(Key *key, const char *filename, const char *passphrase, - const char *comment); - -Key * -key_load_public(const char *filename, char **commentp); - -Key * -key_load_public_type(int type, const char *filename, char **commentp); - -Key * -key_load_private(const char *filename, const char *passphrase, - char **commentp); - -Key * -key_load_private_type(int type, const char *filename, const char *passphrase, - char **commentp); +int key_save_private(Key *, const char *, const char *, const char *); +Key *key_load_public(const char *, char **); +Key *key_load_public_type(int, const char *, char **); +Key *key_load_private(const char *, const char *, char **); +Key *key_load_private_type(int, const char *, const char *, char **); +Key *key_load_private_pem(int, int, const char *, char **); #endif Index: src/crypto/openssh/bufaux.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/bufaux.c,v retrieving revision 1.2.2.3 diff -u -u -r1.2.2.3 bufaux.c --- src/crypto/openssh/bufaux.c 28 Sep 2001 01:33:33 -0000 1.2.2.3 +++ src/crypto/openssh/bufaux.c 30 Jun 2002 11:37:58 -0000 @@ -37,8 +37,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: bufaux.c,v 1.17 2001/01/21 19:05:45 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/bufaux.c,v 1.2.2.3 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/bufaux.c,v 1.12 2002/06/29 11:48:58 des Exp $"); #include #include "bufaux.h" @@ -63,7 +63,7 @@ oi = BN_bn2bin(value, buf); if (oi != bin_size) fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d", - oi, bin_size); + oi, bin_size); /* Store the number of bits in the buffer in two bytes, msb first. */ PUT_16BIT(msg, bits); @@ -78,7 +78,7 @@ /* * Retrieves an BIGNUM from the buffer. */ -int +void buffer_get_bignum(Buffer *buffer, BIGNUM *value) { int bits, bytes; @@ -89,13 +89,13 @@ bits = GET_16BIT(buf); /* Compute the number of binary bytes that follow. */ bytes = (bits + 7) / 8; + if (bytes > 8 * 1024) + fatal("buffer_get_bignum: cannot handle BN of size %d", bytes); if (buffer_len(buffer) < bytes) fatal("buffer_get_bignum: input buffer too small"); - bin = (u_char *) buffer_ptr(buffer); + bin = buffer_ptr(buffer); BN_bin2bn(bin, bytes, value); buffer_consume(buffer, bytes); - - return 2 + bytes; } /* @@ -108,21 +108,22 @@ u_char *buf = xmalloc(bytes); int oi; int hasnohigh = 0; + buf[0] = '\0'; /* Get the value of in binary */ oi = BN_bn2bin(value, buf+1); if (oi != bytes-1) fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d", - oi, bytes); + oi, bytes); hasnohigh = (buf[1] & 0x80) ? 0 : 1; if (value->neg) { /**XXX should be two's-complement */ int i, carry; u_char *uc = buf; log("negativ!"); - for(i = bytes-1, carry = 1; i>=0; i--) { + for (i = bytes-1, carry = 1; i>=0; i--) { uc[i] ^= 0xff; - if(carry) + if (carry) carry = !++uc[i]; } } @@ -131,54 +132,82 @@ xfree(buf); } -int +/* XXX does not handle negative BNs */ +void buffer_get_bignum2(Buffer *buffer, BIGNUM *value) { - /**XXX should be two's-complement */ - int len; - u_char *bin = (u_char *)buffer_get_string(buffer, (u_int *)&len); + u_int len; + u_char *bin = buffer_get_string(buffer, &len); + + if (len > 8 * 1024) + fatal("buffer_get_bignum2: cannot handle BN of size %d", len); BN_bin2bn(bin, len, value); xfree(bin); - return len; } - /* - * Returns an integer from the buffer (4 bytes, msb first). + * Returns integers from the buffer (msb first). */ + +u_short +buffer_get_short(Buffer *buffer) +{ + u_char buf[2]; + + buffer_get(buffer, (char *) buf, 2); + return GET_16BIT(buf); +} + u_int buffer_get_int(Buffer *buffer) { u_char buf[4]; + buffer_get(buffer, (char *) buf, 4); return GET_32BIT(buf); } +#ifdef HAVE_U_INT64_T u_int64_t buffer_get_int64(Buffer *buffer) { u_char buf[8]; + buffer_get(buffer, (char *) buf, 8); return GET_64BIT(buf); } +#endif /* - * Stores an integer in the buffer in 4 bytes, msb first. + * Stores integers in the buffer, msb first. */ void +buffer_put_short(Buffer *buffer, u_short value) +{ + char buf[2]; + + PUT_16BIT(buf, value); + buffer_append(buffer, buf, 2); +} + +void buffer_put_int(Buffer *buffer, u_int value) { char buf[4]; + PUT_32BIT(buf, value); buffer_append(buffer, buf, 4); } +#ifdef HAVE_U_INT64_T void buffer_put_int64(Buffer *buffer, u_int64_t value) { char buf[8]; + PUT_64BIT(buf, value); buffer_append(buffer, buf, 8); } +#endif /* * Returns an arbitrary binary string from the buffer. The string cannot @@ -188,15 +217,16 @@ * will be stored there. A null character will be automatically appended * to the returned string, and is not counted in length. */ -char * +void * buffer_get_string(Buffer *buffer, u_int *length_ptr) { + u_char *value; u_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); + fatal("buffer_get_string: bad string length %d", len); /* Allocate space for the string. Add one byte for a null character. */ value = xmalloc(len + 1); /* Get the string. */ @@ -221,6 +251,8 @@ void buffer_put_cstring(Buffer *buffer, const char *s) { + if (s == NULL) + fatal("buffer_put_cstring: s == NULL"); buffer_put_string(buffer, s, strlen(s)); } @@ -231,6 +263,7 @@ buffer_get_char(Buffer *buffer) { char ch; + buffer_get(buffer, &ch, 1); return (u_char) ch; } @@ -242,5 +275,6 @@ buffer_put_char(Buffer *buffer, int value) { char ch = value; + buffer_append(buffer, &ch, 1); } Index: src/crypto/openssh/bufaux.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/bufaux.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 bufaux.h --- src/crypto/openssh/bufaux.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/bufaux.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: bufaux.h,v 1.18 2002/04/20 09:14:58 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,51 +12,36 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: bufaux.h,v 1.11 2001/01/21 19:05:45 markus Exp $"); */ - #ifndef BUFAUX_H #define BUFAUX_H #include "buffer.h" #include -/* - * Stores an BIGNUM 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_bignum(Buffer * buffer, BIGNUM * value); -void buffer_put_bignum2(Buffer * buffer, BIGNUM * value); - -/* Retrieves an BIGNUM from the buffer. */ -int buffer_get_bignum(Buffer * buffer, BIGNUM * value); -int buffer_get_bignum2(Buffer *buffer, BIGNUM * value); - -/* Returns an integer from the buffer (4 bytes, msb first). */ -u_int buffer_get_int(Buffer * buffer); -u_int64_t buffer_get_int64(Buffer *buffer); - -/* Stores an integer in the buffer in 4 bytes, msb first. */ -void buffer_put_int(Buffer * buffer, u_int value); -void buffer_put_int64(Buffer *buffer, u_int64_t 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, u_int *length_ptr); +void buffer_put_bignum(Buffer *, BIGNUM *); +void buffer_put_bignum2(Buffer *, BIGNUM *); +void buffer_get_bignum(Buffer *, BIGNUM *); +void buffer_get_bignum2(Buffer *, BIGNUM *); + +u_short buffer_get_short(Buffer *); +void buffer_put_short(Buffer *, u_short); + +u_int buffer_get_int(Buffer *); +void buffer_put_int(Buffer *, u_int); + +#ifdef HAVE_U_INT64_T +u_int64_t buffer_get_int64(Buffer *); +void buffer_put_int64(Buffer *, u_int64_t); +#endif + +int buffer_get_char(Buffer *); +void buffer_put_char(Buffer *, int); + +void *buffer_get_string(Buffer *, u_int *); +void buffer_put_string(Buffer *, const void *, u_int); +void buffer_put_cstring(Buffer *, const char *); -/* Stores and arbitrary binary string in the buffer. */ -void buffer_put_string(Buffer * buffer, const void *buf, u_int len); -void buffer_put_cstring(Buffer *buffer, const char *s); +#define buffer_skip_string(b) \ + do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while(0) #endif /* BUFAUX_H */ Index: src/crypto/openssh/buffer.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/buffer.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 buffer.c --- src/crypto/openssh/buffer.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/buffer.c 30 Jun 2002 11:37:58 -0000 @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: buffer.c,v 1.13 2001/04/12 19:15:24 markus Exp $"); +RCSID("$OpenBSD: buffer.c,v 1.16 2002/06/26 08:54:18 markus Exp $"); #include "xmalloc.h" #include "buffer.h" @@ -53,11 +53,11 @@ /* Appends data to the buffer, expanding it if necessary. */ void -buffer_append(Buffer *buffer, const char *data, u_int len) +buffer_append(Buffer *buffer, const void *data, u_int len) { - char *cp; - buffer_append_space(buffer, &cp, len); - memcpy(cp, data, len); + void *p; + p = buffer_append_space(buffer, len); + memcpy(p, data, len); } /* @@ -66,9 +66,14 @@ * to the allocated region. */ -void -buffer_append_space(Buffer *buffer, char **datap, u_int len) +void * +buffer_append_space(Buffer *buffer, u_int len) { + void *p; + + if (len > 0x100000) + fatal("buffer_append_space: len %u not supported", len); + /* If the buffer is empty, start using it from the beginning. */ if (buffer->offset == buffer->end) { buffer->offset = 0; @@ -77,9 +82,9 @@ restart: /* If there is enough space to store all data, store it now. */ if (buffer->end + len < buffer->alloc) { - *datap = buffer->buf + buffer->end; + p = buffer->buf + buffer->end; buffer->end += len; - return; + return p; } /* * If the buffer is quite empty, but all data is at the end, move the @@ -94,8 +99,12 @@ } /* Increase the size of the buffer and retry. */ buffer->alloc += len + 32768; + if (buffer->alloc > 0xa00000) + fatal("buffer_append_space: alloc %u not supported", + buffer->alloc); buffer->buf = xrealloc(buffer->buf, buffer->alloc); goto restart; + /* NOTREACHED */ } /* Returns the number of bytes of data in the buffer. */ @@ -109,7 +118,7 @@ /* Gets data from the beginning of the buffer. */ void -buffer_get(Buffer *buffer, char *buf, u_int len) +buffer_get(Buffer *buffer, void *buf, u_int len) { if (len > buffer->end - buffer->offset) fatal("buffer_get: trying to get more bytes %d than in buffer %d", @@ -140,7 +149,7 @@ /* Returns a pointer to the first used byte in the buffer. */ -char * +void * buffer_ptr(Buffer *buffer) { return buffer->buf + buffer->offset; @@ -152,7 +161,7 @@ buffer_dump(Buffer *buffer) { int i; - u_char *ucp = (u_char *) buffer->buf; + u_char *ucp = buffer->buf; for (i = buffer->offset; i < buffer->end; i++) { fprintf(stderr, "%02x", ucp[i]); Index: src/crypto/openssh/buffer.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/buffer.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 buffer.h --- src/crypto/openssh/buffer.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/buffer.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: buffer.h,v 1.11 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,56 +13,31 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: buffer.h,v 1.7 2000/12/19 23:17:55 markus Exp $"); */ - #ifndef BUFFER_H #define BUFFER_H typedef struct { - char *buf; /* Buffer for data. */ - u_int alloc; /* Number of bytes allocated for data. */ - u_int offset; /* Offset of first byte containing data. */ - u_int end; /* Offset of last byte containing data. */ + u_char *buf; /* Buffer for data. */ + u_int alloc; /* Number of bytes allocated for data. */ + u_int offset; /* Offset of first byte containing data. */ + u_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, u_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, u_int len); - -/* Returns the number of bytes of data in the buffer. */ -u_int buffer_len(Buffer * buffer); +void buffer_init(Buffer *); +void buffer_clear(Buffer *); +void buffer_free(Buffer *); -/* Gets data from the beginning of the buffer. */ -void buffer_get(Buffer * buffer, char *buf, u_int len); +u_int buffer_len(Buffer *); +void *buffer_ptr(Buffer *); -/* Consumes the given number of bytes from the beginning of the buffer. */ -void buffer_consume(Buffer * buffer, u_int bytes); +void buffer_append(Buffer *, const void *, u_int); +void *buffer_append_space(Buffer *, u_int); -/* Consumes the given number of bytes from the end of the buffer. */ -void buffer_consume_end(Buffer * buffer, u_int bytes); +void buffer_get(Buffer *, void *, u_int); -/* Returns a pointer to the first used byte in the buffer. */ -char *buffer_ptr(Buffer * buffer); +void buffer_consume(Buffer *, u_int); +void buffer_consume_end(Buffer *, u_int); -/* - * Dumps the contents of the buffer to stderr in hex. This intended for - * debugging purposes only. - */ -void buffer_dump(Buffer * buffer); +void buffer_dump(Buffer *); #endif /* BUFFER_H */ Index: src/crypto/openssh/canohost.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/canohost.c,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 canohost.c --- src/crypto/openssh/canohost.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/canohost.c 30 Jun 2002 11:37:58 -0000 @@ -12,23 +12,22 @@ */ #include "includes.h" -RCSID("$OpenBSD: canohost.c,v 1.26 2001/04/18 14:15:00 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/canohost.c,v 1.1.1.1.2.5 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: canohost.c,v 1.32 2002/06/11 08:11:45 itojun Exp $"); #include "packet.h" #include "xmalloc.h" #include "log.h" #include "canohost.h" -void check_ip_options(int socket, char *ipaddr); +static void check_ip_options(int, char *); /* * 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, int reverse_mapping_check) +static char * +get_remote_hostname(int socket, int verify_reverse_mapping) { struct sockaddr_storage from; int i; @@ -43,17 +42,40 @@ debug("getpeername failed: %.100s", strerror(errno)); fatal_cleanup(); } - if (from.ss_family == AF_INET) - check_ip_options(socket, ntop); +#ifdef IPV4_IN_IPV6 + if (from.ss_family == AF_INET6) { + struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from; + + /* Detect IPv4 in IPv6 mapped address and convert it to */ + /* plain (AF_INET) IPv4 address */ + if (IN6_IS_ADDR_V4MAPPED(&from6->sin6_addr)) { + struct sockaddr_in *from4 = (struct sockaddr_in *)&from; + struct in_addr addr; + u_int16_t port; + + memcpy(&addr, ((char *)&from6->sin6_addr) + 12, sizeof(addr)); + port = from6->sin6_port; + + memset(&from, 0, sizeof(from)); + + from4->sin_family = AF_INET; + memcpy(&from4->sin_addr, &addr, sizeof(addr)); + from4->sin_port = port; + } + } +#endif if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), - NULL, 0, NI_NUMERICHOST) != 0) + NULL, 0, NI_NUMERICHOST) != 0) fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed"); + if (from.ss_family == AF_INET) + check_ip_options(socket, ntop); + debug3("Trying to reverse map address %.100s.", ntop); /* Map the IP address to a host name. */ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), - NULL, 0, NI_NAMEREQD) != 0) { + NULL, 0, NI_NAMEREQD) != 0) { /* Host name not found. Use ip address. */ log("Could not reverse map address %.100s.", ntop); return xstrdup(ntop); @@ -69,7 +91,7 @@ if (isupper(name[i])) name[i] = tolower(name[i]); - if (!reverse_mapping_check) + if (!verify_reverse_mapping) return xstrdup(name); /* * Map it back to an IP address and check that the given @@ -119,7 +141,7 @@ * exit here if we detect any IP options. */ /* IPv4 only */ -void +static void check_ip_options(int socket, char *ipaddr) { u_char options[200]; @@ -133,7 +155,7 @@ else ipproto = IPPROTO_IP; option_size = sizeof(options); - if (getsockopt(socket, ipproto, IP_OPTIONS, (void *)options, + if (getsockopt(socket, ipproto, IP_OPTIONS, options, &option_size) >= 0 && option_size != 0) { text[0] = '\0'; for (i = 0; i < option_size; i++) @@ -153,14 +175,14 @@ */ const char * -get_canonical_hostname(int reverse_mapping_check) +get_canonical_hostname(int verify_reverse_mapping) { static char *canonical_host_name = NULL; - static int reverse_mapping_checked = 0; + static int verify_reverse_mapping_done = 0; /* Check if we have previously retrieved name with same option. */ if (canonical_host_name != NULL) { - if (reverse_mapping_checked != reverse_mapping_check) + if (verify_reverse_mapping_done != verify_reverse_mapping) xfree(canonical_host_name); else return canonical_host_name; @@ -169,11 +191,11 @@ /* Get the real hostname if socket; otherwise return UNKNOWN. */ if (packet_connection_is_on_socket()) canonical_host_name = get_remote_hostname( - packet_get_connection_in(), reverse_mapping_check); + packet_get_connection_in(), verify_reverse_mapping); else canonical_host_name = xstrdup("UNKNOWN"); - reverse_mapping_checked = reverse_mapping_check; + verify_reverse_mapping_done = verify_reverse_mapping; return canonical_host_name; } @@ -181,7 +203,7 @@ * Returns the remote IP-address of socket as a string. The returned * string must be freed. */ -char * +static char * get_socket_address(int socket, int remote, int flags) { struct sockaddr_storage addr; @@ -209,7 +231,7 @@ } /* Get the address in ascii. */ if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), - NULL, 0, flags) != 0) { + NULL, 0, flags) != 0) { error("get_socket_ipaddr: getnameinfo %d failed", flags); return NULL; } @@ -240,7 +262,7 @@ */ const char * -get_remote_ipaddr() +get_remote_ipaddr(void) { static char *canonical_host_ip = NULL; @@ -260,11 +282,11 @@ } const char * -get_remote_name_or_ip(u_int utmp_len, int reverse_mapping_check) +get_remote_name_or_ip(u_int utmp_len, int verify_reverse_mapping) { static const char *remote = ""; if (utmp_len > 0) - remote = get_canonical_hostname(reverse_mapping_check); + remote = get_canonical_hostname(verify_reverse_mapping); if (utmp_len == 0 || strlen(remote) > utmp_len) remote = get_remote_ipaddr(); return remote; @@ -272,7 +294,7 @@ /* Returns the local/remote port for the socket. */ -int +static int get_sock_port(int sock, int local) { struct sockaddr_storage from; @@ -295,14 +317,14 @@ } /* Return port number. */ if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, - strport, sizeof(strport), NI_NUMERICSERV) != 0) + strport, sizeof(strport), NI_NUMERICSERV) != 0) fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed"); return atoi(strport); } /* Returns remote/local port number for the current connection. */ -int +static int get_port(int local) { /* @@ -323,13 +345,13 @@ } int -get_remote_port() +get_remote_port(void) { return get_port(0); } int -get_local_port() +get_local_port(void) { return get_port(1); } Index: src/crypto/openssh/canohost.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/canohost.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 canohost.h --- src/crypto/openssh/canohost.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/canohost.h 30 Jun 2002 11:37:58 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: canohost.h,v 1.6 2001/04/12 19:15:24 markus Exp $ */ +/* $OpenBSD: canohost.h,v 1.8 2001/06/26 17:27:23 markus Exp $ */ /* * Author: Tatu Ylonen @@ -12,27 +12,14 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* - * 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(int reverse_mapping_check); - -/* - * Returns the IP-address of the remote host as a string. The returned - * string is cached and must not be freed. - */ -const char *get_remote_ipaddr(void); - -const char *get_remote_name_or_ip(u_int utmp_len, int reverse_mapping_check); - -/* Returns the ipaddr/port number of the peer of the socket. */ -char * get_peer_ipaddr(int socket); -int get_peer_port(int sock); -char * get_local_ipaddr(int socket); -char * get_local_name(int socket); +const char *get_canonical_hostname(int); +const char *get_remote_ipaddr(void); +const char *get_remote_name_or_ip(u_int, int); + +char *get_peer_ipaddr(int); +int get_peer_port(int); +char *get_local_ipaddr(int); +char *get_local_name(int); -/* Returns the port number of the remote/local host. */ -int get_remote_port(void); -int get_local_port(void); +int get_remote_port(void); +int get_local_port(void); Index: src/crypto/openssh/channels.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/channels.c,v retrieving revision 1.1.1.1.2.6 diff -u -u -r1.1.1.1.2.6 channels.c --- src/crypto/openssh/channels.c 6 Mar 2002 13:57:54 -0000 1.1.1.1.2.6 +++ src/crypto/openssh/channels.c 30 Jun 2002 11:37:58 -0000 @@ -12,9 +12,8 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * - * * SSH2 support added by Markus Friedl. - * Copyright (c) 1999,2000 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 1999 Dug Song. All rights reserved. * Copyright (c) 1999 Theo de Raadt. All rights reserved. * @@ -40,71 +39,46 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.109 2001/04/17 12:55:03 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/channels.c,v 1.1.1.1.2.6 2002/03/06 13:57:54 nectar Exp $"); - -#include -#include +RCSID("$OpenBSD: channels.c,v 1.179 2002/06/26 08:55:02 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/channels.c,v 1.12 2002/06/29 11:48:58 des Exp $"); #include "ssh.h" #include "ssh1.h" #include "ssh2.h" #include "packet.h" #include "xmalloc.h" -#include "buffer.h" -#include "bufaux.h" -#include "uidswap.h" #include "log.h" #include "misc.h" #include "channels.h" -#include "nchan.h" #include "compat.h" #include "canohost.h" #include "key.h" #include "authfd.h" +#include "pathnames.h" -/* Maximum number of fake X11 displays to try. */ -#define MAX_DISPLAYS 1000 -/* Max len of agent socket */ -#define MAX_SOCKET_NAME 100 +/* -- channel core */ /* * Pointer to an array containing all allocated channels. The array is * dynamically extended as needed. */ -static Channel *channels = NULL; +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. + * initialized (at least the type field); unused slots set to NULL */ static int channels_alloc = 0; /* * Maximum file descriptor value used in any of the channels. This is - * updated in channel_allocate. + * updated in channel_new. */ static int channel_max_fd = 0; -/* Name and directory of socket for authentication agent forwarding. */ -static char *channel_forwarded_auth_socket_name = NULL; -static char *channel_forwarded_auth_socket_dir = 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; -u_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; -u_int x11_fake_data_len; +/* -- tcp forwarding */ /* * Data structure for storing which hosts are permitted for forward requests. @@ -120,6 +94,7 @@ /* 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; /* @@ -129,34 +104,50 @@ */ 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; -/* AF_UNSPEC or AF_INET or AF_INET6 */ -extern int IPv4or6; +/* -- X11 forwarding */ -void port_open_helper(Channel *c, char *rtype); +/* Maximum number of fake X11 displays to try. */ +#define MAX_DISPLAYS 1000 -/* Sets specific protocol options. */ +/* Saved X11 authentication protocol name. */ +static char *x11_saved_proto = NULL; -void -channel_set_options(int hostname_in_open) -{ - have_hostname_in_open = hostname_in_open; -} +/* Saved X11 authentication data. This is the real data. */ +static char *x11_saved_data = NULL; +static u_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. + */ +static char *x11_fake_data = NULL; +static u_int x11_fake_data_len; + + +/* -- agent forwarding */ + +#define NUM_SOCKS 10 -/* lookup channel by id */ +/* AF_UNSPEC or AF_INET or AF_INET6 */ +static int IPv4or6 = AF_UNSPEC; + +/* helper */ +static void port_open_helper(Channel *c, char *rtype); + +/* -- channel core */ Channel * channel_lookup(int id) { Channel *c; + if (id < 0 || id >= channels_alloc) { log("channel_lookup: %d: bad id", id); return NULL; } - c = &channels[id]; - if (c->type == SSH_CHANNEL_FREE) { + c = channels[id]; + if (c == NULL) { log("channel_lookup: %d: bad id: channel free", id); return NULL; } @@ -168,7 +159,7 @@ * when the channel consumer/producer is ready, e.g. shell exec'd */ -void +static void channel_register_fds(Channel *c, int rfd, int wfd, int efd, int extusage, int nonblock) { @@ -213,29 +204,24 @@ * remote_name to be freed. */ -int +Channel * channel_new(char *ctype, int type, int rfd, int wfd, int efd, - int window, int maxpack, int extusage, char *remote_name, int nonblock) + u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) { int i, found; Channel *c; /* Do initial allocation if this is the first call. */ if (channels_alloc == 0) { - chan_init(); channels_alloc = 10; - channels = xmalloc(channels_alloc * sizeof(Channel)); + 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); + channels[i] = NULL; + fatal_add_cleanup((void (*) (void *)) channel_free_all, NULL); } /* Try to find a free slot where to put the new channel. */ for (found = -1, i = 0; i < channels_alloc; i++) - if (channels[i].type == SSH_CHANNEL_FREE) { + if (channels[i] == NULL) { /* Found a free slot. */ found = i; break; @@ -244,17 +230,23 @@ /* There are no free slots. Take last+1 slot and expand the array. */ found = channels_alloc; channels_alloc += 10; + if (channels_alloc > 10000) + fatal("channel_new: internal error: channels_alloc %d " + "too big.", channels_alloc); debug2("channel: expanding %d", channels_alloc); - channels = xrealloc(channels, channels_alloc * sizeof(Channel)); + channels = xrealloc(channels, channels_alloc * sizeof(Channel *)); for (i = found; i < channels_alloc; i++) - channels[i].type = SSH_CHANNEL_FREE; + channels[i] = NULL; } - /* Initialize and return new channel number. */ - c = &channels[found]; + /* Initialize and return new channel. */ + c = channels[found] = xmalloc(sizeof(Channel)); + memset(c, 0, sizeof(Channel)); buffer_init(&c->input); buffer_init(&c->output); buffer_init(&c->extended); - chan_init_iostates(c); + c->ostate = CHAN_OUTPUT_OPEN; + c->istate = CHAN_INPUT_OPEN; + c->flags = 0; channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); c->self = found; c->type = type; @@ -267,73 +259,402 @@ c->remote_name = remote_name; c->remote_window = 0; c->remote_maxpacket = 0; - c->cb_fn = NULL; - c->cb_arg = NULL; - c->cb_event = 0; - c->dettach_user = NULL; + c->force_drain = 0; + c->single_connection = 0; + c->detach_user = NULL; + c->confirm = NULL; c->input_filter = NULL; debug("channel %d: new [%s]", found, remote_name); - return found; + return c; } -/* old interface XXX */ -int -channel_allocate(int type, int sock, char *remote_name) + +static int +channel_find_maxfd(void) { - return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name, 1); + int i, max = 0; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c != NULL) { + max = MAX(max, c->rfd); + max = MAX(max, c->wfd); + max = MAX(max, c->efd); + } + } + return max; } +int +channel_close_fd(int *fdp) +{ + int ret = 0, fd = *fdp; + + if (fd != -1) { + ret = close(fd); + *fdp = -1; + if (fd == channel_max_fd) + channel_max_fd = channel_find_maxfd(); + } + return ret; +} /* Close all channel fd/socket. */ -void +static void channel_close_fds(Channel *c) { - if (c->sock != -1) { - close(c->sock); - c->sock = -1; - } - if (c->rfd != -1) { - close(c->rfd); - c->rfd = -1; - } - if (c->wfd != -1) { - close(c->wfd); - c->wfd = -1; - } - if (c->efd != -1) { - close(c->efd); - c->efd = -1; - } + debug3("channel_close_fds: channel %d: r %d w %d e %d", + c->self, c->rfd, c->wfd, c->efd); + + channel_close_fd(&c->sock); + channel_close_fd(&c->rfd); + channel_close_fd(&c->wfd); + channel_close_fd(&c->efd); } /* Free the channel and close its fd/socket. */ void -channel_free(int id) +channel_free(Channel *c) { - Channel *c = channel_lookup(id); - char *s = channel_open_message(); + char *s; + int i, n; - if (c == NULL) - packet_disconnect("channel free: bad local channel %d", id); - debug("channel_free: channel %d: status: %s", id, s); + for (n = 0, i = 0; i < channels_alloc; i++) + if (channels[i]) + n++; + debug("channel_free: channel %d: %s, nchannels %d", c->self, + c->remote_name ? c->remote_name : "???", n); + + s = channel_open_message(); + debug3("channel_free: status: %s", s); xfree(s); - if (c->dettach_user != NULL) { - debug("channel_free: channel %d: dettaching channel user", id); - c->dettach_user(c->self, NULL); - } if (c->sock != -1) shutdown(c->sock, SHUT_RDWR); channel_close_fds(c); buffer_free(&c->input); buffer_free(&c->output); buffer_free(&c->extended); - c->type = SSH_CHANNEL_FREE; if (c->remote_name) { xfree(c->remote_name); c->remote_name = NULL; } + channels[c->self] = NULL; + xfree(c); +} + +void +channel_free_all(void) +{ + int i; + + for (i = 0; i < channels_alloc; i++) + if (channels[i] != NULL) + channel_free(channels[i]); +} + +/* + * Closes the sockets/fds of all channels. This is used to close extra file + * descriptors after a fork. + */ + +void +channel_close_all(void) +{ + int i; + + for (i = 0; i < channels_alloc; i++) + if (channels[i] != NULL) + channel_close_fds(channels[i]); +} + +/* + * Stop listening to channels. + */ + +void +channel_stop_listening(void) +{ + int i; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c != NULL) { + switch (c->type) { + case SSH_CHANNEL_AUTH_SOCKET: + case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: + case SSH_CHANNEL_X11_LISTENER: + channel_close_fd(&c->sock); + channel_free(c); + break; + } + } + } +} + +/* + * 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(void) +{ + u_int i; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c != NULL && c->type == SSH_CHANNEL_OPEN) { +#if 0 + if (!compat20 && + buffer_len(&c->input) > packet_get_maxsize()) { + debug("channel %d: big input buffer %d", + c->self, buffer_len(&c->input)); + return 0; + } +#endif + if (buffer_len(&c->output) > packet_get_maxsize()) { + debug("channel %d: big output buffer %d > %d", + c->self, buffer_len(&c->output), + packet_get_maxsize()); + return 0; + } + } + } + return 1; +} + +/* Returns true if any channel is still open. */ + +int +channel_still_open(void) +{ + int i; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c == NULL) + continue; + switch (c->type) { + case SSH_CHANNEL_X11_LISTENER: + case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: + case SSH_CHANNEL_CLOSED: + case SSH_CHANNEL_AUTH_SOCKET: + case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_CONNECTING: + case SSH_CHANNEL_ZOMBIE: + continue; + case SSH_CHANNEL_LARVAL: + if (!compat20) + fatal("cannot happen: SSH_CHANNEL_LARVAL"); + continue; + case SSH_CHANNEL_OPENING: + case SSH_CHANNEL_OPEN: + case SSH_CHANNEL_X11_OPEN: + return 1; + case SSH_CHANNEL_INPUT_DRAINING: + case SSH_CHANNEL_OUTPUT_DRAINING: + if (!compat13) + fatal("cannot happen: OUT_DRAIN"); + return 1; + default: + fatal("channel_still_open: bad channel type %d", c->type); + /* NOTREACHED */ + } + } + return 0; +} + +/* Returns the id of an open channel suitable for keepaliving */ + +int +channel_find_open(void) +{ + int i; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c == NULL) + continue; + switch (c->type) { + case SSH_CHANNEL_CLOSED: + case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_X11_LISTENER: + case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: + case SSH_CHANNEL_OPENING: + case SSH_CHANNEL_CONNECTING: + case SSH_CHANNEL_ZOMBIE: + continue; + case SSH_CHANNEL_LARVAL: + case SSH_CHANNEL_AUTH_SOCKET: + case SSH_CHANNEL_OPEN: + case SSH_CHANNEL_X11_OPEN: + return i; + case SSH_CHANNEL_INPUT_DRAINING: + case SSH_CHANNEL_OUTPUT_DRAINING: + if (!compat13) + fatal("cannot happen: OUT_DRAIN"); + return i; + default: + fatal("channel_find_open: bad channel type %d", c->type); + /* NOTREACHED */ + } + } + return -1; +} + + +/* + * 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(void) +{ + Buffer buffer; + Channel *c; + char buf[1024], *cp; + int i; + + buffer_init(&buffer); + snprintf(buf, sizeof buf, "The following connections are open:\r\n"); + buffer_append(&buffer, buf, strlen(buf)); + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c == NULL) + continue; + switch (c->type) { + case SSH_CHANNEL_X11_LISTENER: + case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: + case SSH_CHANNEL_CLOSED: + case SSH_CHANNEL_AUTH_SOCKET: + case SSH_CHANNEL_ZOMBIE: + continue; + case SSH_CHANNEL_LARVAL: + case SSH_CHANNEL_OPENING: + case SSH_CHANNEL_CONNECTING: + case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_OPEN: + case SSH_CHANNEL_X11_OPEN: + case SSH_CHANNEL_INPUT_DRAINING: + case SSH_CHANNEL_OUTPUT_DRAINING: + snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n", + c->self, c->remote_name, + c->type, c->remote_id, + c->istate, buffer_len(&c->input), + c->ostate, buffer_len(&c->output), + c->rfd, c->wfd); + buffer_append(&buffer, buf, strlen(buf)); + continue; + default: + fatal("channel_open_message: bad channel type %d", c->type); + /* NOTREACHED */ + } + } + buffer_append(&buffer, "\0", 1); + cp = xstrdup(buffer_ptr(&buffer)); + buffer_free(&buffer); + return cp; +} + +void +channel_send_open(int id) +{ + Channel *c = channel_lookup(id); + if (c == NULL) { + log("channel_send_open: %d: bad id", id); + return; + } + debug("send channel open %d", id); + packet_start(SSH2_MSG_CHANNEL_OPEN); + packet_put_cstring(c->ctype); + packet_put_int(c->self); + packet_put_int(c->local_window); + packet_put_int(c->local_maxpacket); + packet_send(); +} + +void +channel_request_start(int local_id, char *service, int wantconfirm) +{ + Channel *c = channel_lookup(local_id); + if (c == NULL) { + log("channel_request_start: %d: unknown channel id", local_id); + return; + } + debug("channel request %d: %s", local_id, service) ; + packet_start(SSH2_MSG_CHANNEL_REQUEST); + packet_put_int(c->remote_id); + packet_put_cstring(service); + packet_put_char(wantconfirm); +} +void +channel_register_confirm(int id, channel_callback_fn *fn) +{ + Channel *c = channel_lookup(id); + if (c == NULL) { + log("channel_register_comfirm: %d: bad id", id); + return; + } + c->confirm = fn; +} +void +channel_register_cleanup(int id, channel_callback_fn *fn) +{ + Channel *c = channel_lookup(id); + if (c == NULL) { + log("channel_register_cleanup: %d: bad id", id); + return; + } + c->detach_user = fn; +} +void +channel_cancel_cleanup(int id) +{ + Channel *c = channel_lookup(id); + if (c == NULL) { + log("channel_cancel_cleanup: %d: bad id", id); + return; + } + c->detach_user = NULL; +} +void +channel_register_filter(int id, channel_filter_fn *fn) +{ + Channel *c = channel_lookup(id); + if (c == NULL) { + log("channel_register_filter: %d: bad id", id); + return; + } + c->input_filter = fn; +} + +void +channel_set_fds(int id, int rfd, int wfd, int efd, + int extusage, int nonblock, u_int window_max) +{ + Channel *c = channel_lookup(id); + if (c == NULL || c->type != SSH_CHANNEL_LARVAL) + fatal("channel_activate for non-larval channel %d.", id); + channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); + c->type = SSH_CHANNEL_OPEN; + c->local_window = c->local_window_max = window_max; + packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); + packet_put_int(c->remote_id); + packet_put_int(c->local_window); + packet_send(); } /* @@ -348,20 +669,20 @@ chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE]; chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE]; -void +static void channel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset) { FD_SET(c->sock, readset); } -void +static void channel_pre_connecting(Channel *c, fd_set * readset, fd_set * writeset) { debug3("channel %d: waiting for connection", c->self); FD_SET(c->sock, writeset); } -void +static void channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset) { if (buffer_len(&c->input) < packet_get_maxsize()) @@ -370,50 +691,40 @@ FD_SET(c->sock, writeset); } -void -channel_pre_open_15(Channel *c, fd_set * readset, fd_set * writeset) +static void +channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) { - /* test whether sockets are 'alive' for read/write */ - if (c->istate == CHAN_INPUT_OPEN) - if (buffer_len(&c->input) < packet_get_maxsize()) - FD_SET(c->sock, readset); - if (c->ostate == CHAN_OUTPUT_OPEN || - c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - if (buffer_len(&c->output) > 0) { - FD_SET(c->sock, writeset); - } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - chan_obuf_empty(c); - } - } -} + u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); -void -channel_pre_open_20(Channel *c, fd_set * readset, fd_set * writeset) -{ if (c->istate == CHAN_INPUT_OPEN && - c->remote_window > 0 && - buffer_len(&c->input) < c->remote_window) + limit > 0 && + buffer_len(&c->input) < limit) FD_SET(c->rfd, readset); if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (buffer_len(&c->output) > 0) { FD_SET(c->wfd, writeset); } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - chan_obuf_empty(c); + if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) + debug2("channel %d: obuf_empty delayed efd %d/(%d)", + c->self, c->efd, buffer_len(&c->extended)); + else + chan_obuf_empty(c); } } /** XXX check close conditions, too */ - if (c->efd != -1) { + if (compat20 && c->efd != -1) { if (c->extended_usage == CHAN_EXTENDED_WRITE && buffer_len(&c->extended) > 0) FD_SET(c->efd, writeset); - else if (c->extended_usage == CHAN_EXTENDED_READ && + else if (!(c->flags & CHAN_EOF_SENT) && + c->extended_usage == CHAN_EXTENDED_READ && buffer_len(&c->extended) < c->remote_window) FD_SET(c->efd, readset); } } -void +static void channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset) { if (buffer_len(&c->input) == 0) { @@ -425,11 +736,11 @@ } } -void +static void channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset) { if (buffer_len(&c->output) == 0) - channel_free(c->self); + chan_mark_dead(c); else FD_SET(c->sock, writeset); } @@ -441,19 +752,20 @@ * 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. * XXX All this happens at the client side. + * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok */ -int -x11_open_helper(Channel *c) +static int +x11_open_helper(Buffer *b) { u_char *ucp; u_int proto_len, data_len; /* Check if the fixed size part of the packet is in buffer. */ - if (buffer_len(&c->output) < 12) + if (buffer_len(b) < 12) return 0; /* Parse the lengths of variable-length fields. */ - ucp = (u_char *) buffer_ptr(&c->output); + ucp = buffer_ptr(b); if (ucp[0] == 0x42) { /* Byte order MSB first. */ proto_len = 256 * ucp[6] + ucp[7]; data_len = 256 * ucp[8] + ucp[9]; @@ -462,12 +774,12 @@ data_len = ucp[8] + 256 * ucp[9]; } else { debug("Initial X11 packet contains bad byte order byte: 0x%x", - ucp[0]); + ucp[0]); return -1; } /* Check if the whole packet is in buffer. */ - if (buffer_len(&c->output) < + if (buffer_len(b) < 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) return 0; @@ -500,10 +812,10 @@ return 1; } -void +static void channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset) { - int ret = x11_open_helper(c); + int ret = x11_open_helper(&c->output); if (ret == 1) { /* Start normal processing for the channel. */ c->type = SSH_CHANNEL_OPEN; @@ -516,7 +828,7 @@ log("X11 connection rejected because of wrong authentication."); buffer_clear(&c->input); buffer_clear(&c->output); - close(c->sock); + channel_close_fd(&c->sock); c->sock = -1; c->type = SSH_CHANNEL_CLOSED; packet_start(SSH_MSG_CHANNEL_CLOSE); @@ -525,31 +837,39 @@ } } -void +static void channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset) { - int ret = x11_open_helper(c); + int ret = x11_open_helper(&c->output); + + /* c->force_drain = 1; */ + if (ret == 1) { c->type = SSH_CHANNEL_OPEN; - if (compat20) - channel_pre_open_20(c, readset, writeset); - else - channel_pre_open_15(c, readset, writeset); + channel_pre_open(c, readset, writeset); } else if (ret == -1) { + log("X11 connection rejected because of wrong authentication."); debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); - chan_read_failed(c); /** force close? */ - chan_write_failed(c); + chan_read_failed(c); + buffer_clear(&c->input); + chan_ibuf_empty(c); + buffer_clear(&c->output); + /* for proto v1, the peer will send an IEOF */ + if (compat20) + chan_write_failed(c); + else + c->type = SSH_CHANNEL_OPEN; debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); } } /* try to decode a socks4 header */ -int +static int channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset) { u_char *p, *host; int len, have, i, found; - char username[256]; + char username[256]; struct { u_int8_t version; u_int8_t command; @@ -596,7 +916,7 @@ host = inet_ntoa(s4_req.dest_addr); strlcpy(c->path, host, sizeof(c->path)); c->host_port = ntohs(s4_req.dest_port); - + debug("channel %d: dynamic request: socks4 host %s port %u command %u", c->self, host, c->host_port, s4_req.command); @@ -614,14 +934,14 @@ } /* dynamic port forwarding */ -void +static void channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) { u_char *p; int have, ret; have = buffer_len(&c->input); - + c->delayed = 0; debug2("channel %d: pre_dynamic: have %d", c->self, have); /* buffer_dump(&c->input); */ /* check if the fixed size part of the packet is in buffer. */ @@ -641,7 +961,7 @@ break; } if (ret < 0) { - channel_free(c->self); + chan_mark_dead(c); } else if (ret == 0) { debug2("channel %d: pre_dynamic: need more", c->self); /* need more */ @@ -654,11 +974,12 @@ } /* This is our fake X11 server socket. */ -void +static void channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) { + Channel *nc; struct sockaddr addr; - int newsock, newch; + int newsock; socklen_t addrlen; char buf[16384], *remote_ipaddr; int remote_port; @@ -667,25 +988,31 @@ debug("X11 connection requested."); addrlen = sizeof(addr); newsock = accept(c->sock, &addr, &addrlen); + if (c->single_connection) { + debug("single_connection: closing X11 listener."); + channel_close_fd(&c->sock); + chan_mark_dead(c); + } if (newsock < 0) { error("accept: %.100s", strerror(errno)); return; } + set_nodelay(newsock); remote_ipaddr = get_peer_ipaddr(newsock); remote_port = get_peer_port(newsock); snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", remote_ipaddr, remote_port); - newch = channel_new("x11", + nc = channel_new("accepted x11 socket", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(buf), 1); if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring("x11"); - packet_put_int(newch); - packet_put_int(c->local_window_max); - packet_put_int(c->local_maxpacket); + packet_put_int(nc->self); + packet_put_int(nc->local_window_max); + packet_put_int(nc->local_maxpacket); /* originator ipaddr and port */ packet_put_cstring(remote_ipaddr); if (datafellows & SSH_BUG_X11FWD) { @@ -696,16 +1023,17 @@ packet_send(); } else { packet_start(SSH_SMSG_X11_OPEN); - packet_put_int(newch); - if (have_hostname_in_open) - packet_put_string(buf, strlen(buf)); + packet_put_int(nc->self); + if (packet_get_protocol_flags() & + SSH_PROTOFLAG_HOST_IN_FWD_OPEN) + packet_put_cstring(buf); packet_send(); } xfree(remote_ipaddr); } } -void +static void port_open_helper(Channel *c, char *rtype) { int direct; @@ -748,7 +1076,8 @@ packet_put_int(c->self); packet_put_cstring(c->path); packet_put_int(c->host_port); - if (have_hostname_in_open) + if (packet_get_protocol_flags() & + SSH_PROTOFLAG_HOST_IN_FWD_OPEN) packet_put_cstring(c->remote_name); packet_send(); } @@ -758,12 +1087,12 @@ /* * This socket is listening for connections to a forwarded TCP/IP port. */ -void +static void channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) { Channel *nc; struct sockaddr addr; - int newsock, newch, nextstate; + int newsock, nextstate; socklen_t addrlen; char *rtype; @@ -772,10 +1101,18 @@ "to %.100s port %d requested.", c->listening_port, c->path, c->host_port); - rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ? - "forwarded-tcpip" : "direct-tcpip"; - nextstate = (c->host_port == 0) ? SSH_CHANNEL_DYNAMIC : - SSH_CHANNEL_OPENING; + if (c->type == SSH_CHANNEL_RPORT_LISTENER) { + nextstate = SSH_CHANNEL_OPENING; + rtype = "forwarded-tcpip"; + } else { + if (c->host_port == 0) { + nextstate = SSH_CHANNEL_DYNAMIC; + rtype = "dynamic-tcpip"; + } else { + nextstate = SSH_CHANNEL_OPENING; + rtype = "direct-tcpip"; + } + } addrlen = sizeof(addr); newsock = accept(c->sock, &addr, &addrlen); @@ -783,22 +1120,25 @@ error("accept: %.100s", strerror(errno)); return; } - newch = channel_new(rtype, + set_nodelay(newsock); + nc = channel_new(rtype, nextstate, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(rtype), 1); - - nc = channel_lookup(newch); - if (nc == NULL) { - error("xxx: no new channel:"); - return; - } nc->listening_port = c->listening_port; nc->host_port = c->host_port; strlcpy(nc->path, c->path, sizeof(nc->path)); - if (nextstate != SSH_CHANNEL_DYNAMIC) + if (nextstate == SSH_CHANNEL_DYNAMIC) { + /* + * do not call the channel_post handler until + * this flag has been reset by a pre-handler. + * otherwise the FD_ISSET calls might overflow + */ + nc->delayed = 1; + } else { port_open_helper(nc, rtype); + } } } @@ -806,11 +1146,13 @@ * This is the authentication agent socket listening for connections from * clients. */ -void +static void channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) { + Channel *nc; + char *name; + int newsock; struct sockaddr addr; - int newsock, newch; socklen_t addrlen; if (FD_ISSET(c->sock, readset)) { @@ -820,47 +1162,72 @@ error("accept from auth socket: %.100s", strerror(errno)); return; } - newch = channel_new("accepted auth socket", + name = xstrdup("accepted auth socket"); + nc = channel_new("accepted auth socket", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, - 0, xstrdup("accepted auth socket"), 1); + 0, name, 1); if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring("auth-agent@openssh.com"); - packet_put_int(newch); + packet_put_int(nc->self); packet_put_int(c->local_window_max); packet_put_int(c->local_maxpacket); } else { packet_start(SSH_SMSG_AGENT_OPEN); - packet_put_int(newch); + packet_put_int(nc->self); } packet_send(); } } -void +static void channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset) { + int err = 0; + socklen_t sz = sizeof(err); + if (FD_ISSET(c->sock, writeset)) { - int err = 0; - int sz = sizeof(err); - c->type = SSH_CHANNEL_OPEN; - if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &sz) < 0) { - debug("getsockopt SO_ERROR failed"); + if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { + err = errno; + error("getsockopt SO_ERROR failed"); + } + if (err == 0) { + debug("channel %d: connected", c->self); + c->type = SSH_CHANNEL_OPEN; + if (compat20) { + packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(c->remote_id); + packet_put_int(c->self); + packet_put_int(c->local_window); + packet_put_int(c->local_maxpacket); + } else { + packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(c->remote_id); + packet_put_int(c->self); + } } else { - if (err == 0) { - debug("channel %d: connected)", c->self); + debug("channel %d: not connected: %s", + c->self, strerror(err)); + if (compat20) { + packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(c->remote_id); + packet_put_int(SSH2_OPEN_CONNECT_FAILED); + if (!(datafellows & SSH_BUG_OPENFAILURE)) { + packet_put_cstring(strerror(err)); + packet_put_cstring(""); + } } else { - debug("channel %d: not connected: %s", - c->self, strerror(err)); - chan_read_failed(c); - chan_write_failed(c); + packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(c->remote_id); } + chan_mark_dead(c); } + packet_send(); } } -int +static int channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) { char buf[16*1024]; @@ -876,18 +1243,18 @@ c->self, c->rfd, len); if (c->type != SSH_CHANNEL_OPEN) { debug("channel %d: not open", c->self); - channel_free(c->self); + chan_mark_dead(c); return -1; } else if (compat13) { - buffer_consume(&c->output, buffer_len(&c->output)); + buffer_clear(&c->output); c->type = SSH_CHANNEL_INPUT_DRAINING; - debug("channel %d: status set to input draining.", c->self); + debug("channel %d: input draining.", c->self); } else { chan_read_failed(c); } return -1; } - if(c->input_filter != NULL) { + if (c->input_filter != NULL) { if (c->input_filter(c, buf, len) == -1) { debug("channel %d: filter stops", c->self); chan_read_failed(c); @@ -898,35 +1265,38 @@ } return 1; } -int +static int channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) { struct termios tio; + u_char *data; + u_int dlen; int len; /* Send buffered output data to the socket. */ if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) && buffer_len(&c->output) > 0) { - len = write(c->wfd, buffer_ptr(&c->output), - buffer_len(&c->output)); + data = buffer_ptr(&c->output); + dlen = buffer_len(&c->output); + len = write(c->wfd, data, dlen); if (len < 0 && (errno == EINTR || errno == EAGAIN)) return 1; if (len <= 0) { if (c->type != SSH_CHANNEL_OPEN) { debug("channel %d: not open", c->self); - channel_free(c->self); + chan_mark_dead(c); return -1; } else if (compat13) { - buffer_consume(&c->output, buffer_len(&c->output)); - debug("channel %d: status set to input draining.", c->self); + buffer_clear(&c->output); + debug("channel %d: input draining.", c->self); c->type = SSH_CHANNEL_INPUT_DRAINING; } else { chan_write_failed(c); } return -1; } - if (compat20 && c->isatty) { + if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') { if (tcgetattr(c->wfd, &tio) == 0 && !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { /* @@ -946,7 +1316,7 @@ } return 1; } -int +static int channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) { char buf[16*1024]; @@ -966,8 +1336,7 @@ if (len <= 0) { debug2("channel %d: closing write-efd %d", c->self, c->efd); - close(c->efd); - c->efd = -1; + channel_close_fd(&c->efd); } else { buffer_consume(&c->extended, len); c->local_consumed += len; @@ -976,14 +1345,13 @@ FD_ISSET(c->efd, readset)) { len = read(c->efd, buf, sizeof(buf)); debug2("channel %d: read %d from efd %d", - c->self, len, c->efd); + c->self, len, c->efd); if (len < 0 && (errno == EINTR || errno == EAGAIN)) return 1; if (len <= 0) { debug2("channel %d: closing read-efd %d", c->self, c->efd); - close(c->efd); - c->efd = -1; + channel_close_fd(&c->efd); } else { buffer_append(&c->extended, buf, len); } @@ -991,7 +1359,7 @@ } return 1; } -int +static int channel_check_window(Channel *c) { if (c->type == SSH_CHANNEL_OPEN && @@ -1011,24 +1379,20 @@ return 1; } -void -channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset) -{ - channel_handle_rfd(c, readset, writeset); - channel_handle_wfd(c, readset, writeset); -} - -void -channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset) +static void +channel_post_open(Channel *c, fd_set * readset, fd_set * writeset) { + if (c->delayed) + return; channel_handle_rfd(c, readset, writeset); channel_handle_wfd(c, readset, writeset); + if (!compat20) + return; channel_handle_efd(c, readset, writeset); - channel_check_window(c); } -void +static void channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset) { int len; @@ -1037,16 +1401,16 @@ len = write(c->sock, buffer_ptr(&c->output), buffer_len(&c->output)); if (len <= 0) - buffer_consume(&c->output, buffer_len(&c->output)); + buffer_clear(&c->output); else buffer_consume(&c->output, len); } } -void +static void channel_handler_init_20(void) { - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; + channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; @@ -1055,16 +1419,16 @@ channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; + channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open_2; + channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; } -void +static void channel_handler_init_13(void) { channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13; @@ -1077,19 +1441,19 @@ channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; + channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open_1; + channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; } -void +static void channel_handler_init_15(void) { - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_15; + channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; @@ -1100,16 +1464,16 @@ channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; + channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open_1; + channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; } -void +static void channel_handler_init(void) { int i; - for(i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { + for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { channel_pre[i] = NULL; channel_post[i] = NULL; } @@ -1121,7 +1485,29 @@ channel_handler_init_15(); } -void +/* gc dead channels */ +static void +channel_garbage_collect(Channel *c) +{ + if (c == NULL) + return; + if (c->detach_user != NULL) { + if (!chan_is_dead(c, 0)) + return; + debug("channel %d: gc: notify user", c->self); + c->detach_user(c->self, NULL); + /* if we still have a callback */ + if (c->detach_user != NULL) + return; + debug("channel %d: gc: user detached", c->self); + } + if (!chan_is_dead(c, 1)) + return; + debug("channel %d: garbage collecting", c->self); + channel_free(c); +} + +static void channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) { static int did_init = 0; @@ -1133,36 +1519,22 @@ did_init = 1; } for (i = 0; i < channels_alloc; i++) { - c = &channels[i]; - if (c->type == SSH_CHANNEL_FREE) - continue; - if (ftab[c->type] == NULL) + c = channels[i]; + if (c == NULL) continue; - (*ftab[c->type])(c, readset, writeset); - if (chan_is_dead(c)) { - /* - * we have to remove the fd's from the select mask - * before the channels are free'd and the fd's are - * closed - */ - if (c->wfd != -1) - FD_CLR(c->wfd, writeset); - if (c->rfd != -1) - FD_CLR(c->rfd, readset); - if (c->efd != -1) { - if (c->extended_usage == CHAN_EXTENDED_READ) - FD_CLR(c->efd, readset); - if (c->extended_usage == CHAN_EXTENDED_WRITE) - FD_CLR(c->efd, writeset); - } - channel_free(c->self); - } + if (ftab[c->type] != NULL) + (*ftab[c->type])(c, readset, writeset); + channel_garbage_collect(c); } } +/* + * Allocate/update select bitmasks and add any bits relevant to channels in + * select bitmasks. + */ void channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, - int rekeying) + int *nallocp, int rekeying) { int n; u_int sz; @@ -1170,15 +1542,13 @@ n = MAX(*maxfdp, channel_max_fd); sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); - if (*readsetp == NULL || n > *maxfdp) { - if (*readsetp) - xfree(*readsetp); - if (*writesetp) - xfree(*writesetp); - *readsetp = xmalloc(sz); - *writesetp = xmalloc(sz); - *maxfdp = n; + /* perhaps check sz < nalloc/2 and shrink? */ + if (*readsetp == NULL || sz > *nallocp) { + *readsetp = xrealloc(*readsetp, sz); + *writesetp = xrealloc(*writesetp, sz); + *nallocp = sz; } + *maxfdp = n; memset(*readsetp, 0, sz); memset(*writesetp, 0, sz); @@ -1186,24 +1556,35 @@ channel_handler(channel_pre, *readsetp, *writesetp); } +/* + * After select, perform any appropriate operations for channels which have + * events pending. + */ void channel_after_select(fd_set * readset, fd_set * writeset) { channel_handler(channel_post, readset, writeset); } + /* If there is data to send to the connection, enqueue some of it now. */ void -channel_output_poll() +channel_output_poll(void) { - int len, i; Channel *c; + int i; + u_int len; for (i = 0; i < channels_alloc; i++) { - c = &channels[i]; + c = channels[i]; + if (c == NULL) + continue; - /* We are only interested in channels that can have buffered incoming data. */ + /* + * We are only interested in channels that can have buffered + * incoming data. + */ if (compat13) { if (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_INPUT_DRAINING) @@ -1215,7 +1596,7 @@ if (compat20 && (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { /* XXX is this true? */ - debug2("channel %d: no data after CLOSE", c->self); + debug3("channel %d: will not send data after close", c->self); continue; } @@ -1223,7 +1604,10 @@ if ((c->istate == CHAN_INPUT_OPEN || c->istate == CHAN_INPUT_WAIT_DRAIN) && (len = buffer_len(&c->input)) > 0) { - /* Send some data for the other side over the secure connection. */ + /* + * Send some data for the other side over the secure + * connection. + */ if (compat20) { if (len > c->remote_window) len = c->remote_window; @@ -1253,16 +1637,22 @@ fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); /* * input-buffer is empty and read-socket shutdown: - * tell peer, that we will not send more data: send IEOF + * tell peer, that we will not send more data: send IEOF. + * hack for extended data: delay EOF if EFD still in use. */ - chan_ibuf_empty(c); + if (CHANNEL_EFD_INPUT_ACTIVE(c)) + debug2("channel %d: ibuf_empty delayed efd %d/(%d)", + c->self, c->efd, buffer_len(&c->extended)); + else + chan_ibuf_empty(c); } /* Send extended data, i.e. stderr */ if (compat20 && + !(c->flags & CHAN_EOF_SENT) && c->remote_window > 0 && (len = buffer_len(&c->extended)) > 0 && c->extended_usage == CHAN_EXTENDED_READ) { - debug2("channel %d: rwin %d elen %d euse %d", + debug2("channel %d: rwin %u elen %u euse %d", c->self, c->remote_window, buffer_len(&c->extended), c->extended_usage); if (len > c->remote_window) @@ -1281,14 +1671,11 @@ } } -/* - * 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. - */ + +/* -- protocol input */ void -channel_input_data(int type, int plen, void *ctxt) +channel_input_data(int type, u_int32_t seq, void *ctxt) { int id; char *data; @@ -1312,9 +1699,8 @@ /* Get the data. */ data = packet_get_string(&data_len); - packet_done(); - if (compat20){ + if (compat20) { if (data_len > c->local_maxpacket) { log("channel %d: rcvd big packet %d, maxpack %d", c->self, data_len, c->local_maxpacket); @@ -1326,19 +1712,18 @@ return; } c->local_window -= data_len; - }else{ - packet_integrity_check(plen, 4 + 4 + data_len, type); } + packet_check_eom(); buffer_append(&c->output, data, data_len); xfree(data); } + void -channel_input_extended_data(int type, int plen, void *ctxt) +channel_input_extended_data(int type, u_int32_t seq, void *ctxt) { int id; - int tcode; char *data; - u_int data_len; + u_int data_len, tcode; Channel *c; /* Get the channel number and verify it. */ @@ -1351,6 +1736,13 @@ log("channel %d: ext data for non open", id); return; } + if (c->flags & CHAN_EOF_RCVD) { + if (datafellows & SSH_BUG_EXTEOF) + debug("channel %d: accepting ext data after eof", id); + else + packet_disconnect("Received extended_data after EOF " + "on channel %d.", id); + } tcode = packet_get_int(); if (c->efd == -1 || c->extended_usage != CHAN_EXTENDED_WRITE || @@ -1359,7 +1751,7 @@ return; } data = packet_get_string(&data_len); - packet_done(); + packet_check_eom(); if (data_len > c->local_window) { log("channel %d: rcvd too much extended_data %d, win %d", c->self, data_len, c->local_window); @@ -1372,60 +1764,37 @@ 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() -{ - u_int i; - Channel *c; - - for (i = 0; i < channels_alloc; i++) { - c = &channels[i]; - if (c->type == SSH_CHANNEL_OPEN) { - if (!compat20 && buffer_len(&c->input) > packet_get_maxsize()) { - debug("channel %d: big input buffer %d", - c->self, buffer_len(&c->input)); - return 0; - } - if (buffer_len(&c->output) > packet_get_maxsize()) { - debug("channel %d: big output buffer %d", - c->self, buffer_len(&c->output)); - return 0; - } - } - } - return 1; -} - void -channel_input_ieof(int type, int plen, void *ctxt) +channel_input_ieof(int type, u_int32_t seq, void *ctxt) { int id; Channel *c; - packet_integrity_check(plen, 4, type); - id = packet_get_int(); + packet_check_eom(); c = channel_lookup(id); if (c == NULL) packet_disconnect("Received ieof for nonexistent channel %d.", id); chan_rcvd_ieof(c); + + /* XXX force input close */ + if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { + debug("channel %d: FORCE input drain", c->self); + c->istate = CHAN_INPUT_WAIT_DRAIN; + if (buffer_len(&c->input) == 0) + chan_ibuf_empty(c); + } + } void -channel_input_close(int type, int plen, void *ctxt) +channel_input_close(int type, u_int32_t seq, void *ctxt) { int id; Channel *c; - packet_integrity_check(plen, 4, type); - id = packet_get_int(); + packet_check_eom(); c = channel_lookup(id); if (c == NULL) packet_disconnect("Received close for nonexistent channel %d.", id); @@ -1450,48 +1819,46 @@ * Not a closed channel - mark it as draining, which will * cause it to be freed later. */ - buffer_consume(&c->input, buffer_len(&c->input)); + buffer_clear(&c->input); c->type = SSH_CHANNEL_OUTPUT_DRAINING; } } /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ void -channel_input_oclose(int type, int plen, void *ctxt) +channel_input_oclose(int type, u_int32_t seq, void *ctxt) { int id = packet_get_int(); Channel *c = channel_lookup(id); - packet_integrity_check(plen, 4, type); + + packet_check_eom(); if (c == NULL) packet_disconnect("Received oclose for nonexistent channel %d.", id); chan_rcvd_oclose(c); } void -channel_input_close_confirmation(int type, int plen, void *ctxt) +channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt) { int id = packet_get_int(); Channel *c = channel_lookup(id); - packet_done(); + packet_check_eom(); if (c == NULL) packet_disconnect("Received close confirmation for " "out-of-range channel %d.", id); if (c->type != SSH_CHANNEL_CLOSED) packet_disconnect("Received close confirmation for " "non-closed channel %d (type %d).", id, c->type); - channel_free(c->self); + channel_free(c); } void -channel_input_open_confirmation(int type, int plen, void *ctxt) +channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) { int id, remote_id; Channel *c; - if (!compat20) - packet_integrity_check(plen, 4 + 4, type); - id = packet_get_int(); c = channel_lookup(id); @@ -1506,27 +1873,40 @@ if (compat20) { c->remote_window = packet_get_int(); c->remote_maxpacket = packet_get_int(); - packet_done(); - if (c->cb_fn != NULL && c->cb_event == type) { + if (c->confirm) { debug2("callback start"); - c->cb_fn(c->self, c->cb_arg); + c->confirm(c->self, NULL); debug2("callback done"); } - debug("channel %d: open confirm rwindow %d rmax %d", c->self, + debug("channel %d: open confirm rwindow %u rmax %u", c->self, c->remote_window, c->remote_maxpacket); } + packet_check_eom(); +} + +static char * +reason2txt(int reason) +{ + switch (reason) { + case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED: + return "administratively prohibited"; + case SSH2_OPEN_CONNECT_FAILED: + return "connect failed"; + case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE: + return "unknown channel type"; + case SSH2_OPEN_RESOURCE_SHORTAGE: + return "resource shortage"; + } + return "unknown reason"; } void -channel_input_open_failure(int type, int plen, void *ctxt) +channel_input_open_failure(int type, u_int32_t seq, void *ctxt) { int id, reason; char *msg = NULL, *lang = NULL; Channel *c; - if (!compat20) - packet_integrity_check(plen, 4, type); - id = packet_get_int(); c = channel_lookup(id); @@ -1535,52 +1915,28 @@ "non-opening channel %d.", id); if (compat20) { reason = packet_get_int(); - if (packet_remaining() > 0) { + if (!(datafellows & SSH_BUG_OPENFAILURE)) { msg = packet_get_string(NULL); lang = packet_get_string(NULL); } - packet_done(); - log("channel_open_failure: %d: reason %d %s", id, - reason, msg ? msg : ""); + log("channel %d: open failed: %s%s%s", id, + reason2txt(reason), msg ? ": ": "", msg ? msg : ""); if (msg != NULL) xfree(msg); if (lang != NULL) xfree(lang); } + packet_check_eom(); /* Free the channel. This will also close the socket. */ - channel_free(id); -} - -void -channel_input_channel_request(int type, int plen, void *ctxt) -{ - int id; - Channel *c; - - id = packet_get_int(); - c = channel_lookup(id); - - if (c == NULL || - (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_LARVAL)) - packet_disconnect("Received request for " - "non-open channel %d.", id); - if (c->cb_fn != NULL && c->cb_event == type) { - debug2("callback start"); - c->cb_fn(c->self, c->cb_arg); - debug2("callback done"); - } else { - char *service = packet_get_string(NULL); - debug("channel %d: rcvd request for %s", c->self, service); - debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event); - xfree(service); - } + channel_free(c); } void -channel_input_window_adjust(int type, int plen, void *ctxt) +channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) { Channel *c; - int id, adjust; + int id; + u_int adjust; if (!compat20) return; @@ -1595,224 +1951,77 @@ return; } adjust = packet_get_int(); - packet_done(); - debug2("channel %d: rcvd adjust %d", id, adjust); + packet_check_eom(); + debug2("channel %d: rcvd adjust %u", id, adjust); c->remote_window += adjust; -} - -/* - * 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); - /* auth_sock_cleanup_proc deletes the socket */ - channel_free(i); - break; - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_X11_LISTENER: - close(channels[i].sock); - channel_free(i); - break; - default: - break; - } - } -} - -/* - * Closes the sockets/fds 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) - channel_close_fds(&channels[i]); -} - -/* Returns true if any channel is still open. */ - -int -channel_still_open() -{ - u_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_RPORT_LISTENER: - case SSH_CHANNEL_CLOSED: - case SSH_CHANNEL_AUTH_SOCKET: - case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_CONNECTING: /* XXX ??? */ - continue; - case SSH_CHANNEL_LARVAL: - if (!compat20) - fatal("cannot happen: SSH_CHANNEL_LARVAL"); - continue; - case SSH_CHANNEL_OPENING: - case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_X11_OPEN: - return 1; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - if (!compat13) - fatal("cannot happen: OUT_DRAIN"); - return 1; - default: - fatal("channel_still_open: bad channel type %d", channels[i].type); - /* NOTREACHED */ - } - return 0; -} - -/* Returns the id of an open channel suitable for keepaliving */ - -int -channel_find_open() -{ - u_int i; - for (i = 0; i < channels_alloc; i++) - switch (channels[i].type) { - case SSH_CHANNEL_CLOSED: - case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_FREE: - case SSH_CHANNEL_X11_LISTENER: - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_OPENING: - continue; - case SSH_CHANNEL_LARVAL: - case SSH_CHANNEL_AUTH_SOCKET: - case SSH_CHANNEL_CONNECTING: /* XXX ??? */ - case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_X11_OPEN: - return i; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - if (!compat13) - fatal("cannot happen: OUT_DRAIN"); - return i; - default: - fatal("channel_find_open: bad channel type %d", channels[i].type); - /* NOTREACHED */ - } - return -1; -} - - -/* - * 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); - snprintf(buf, sizeof buf, "The following connections are open:\r\n"); - buffer_append(&buffer, buf, strlen(buf)); - for (i = 0; i < channels_alloc; i++) { - Channel *c = &channels[i]; - switch (c->type) { - case SSH_CHANNEL_FREE: - case SSH_CHANNEL_X11_LISTENER: - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_CLOSED: - case SSH_CHANNEL_AUTH_SOCKET: - continue; - case SSH_CHANNEL_LARVAL: - case SSH_CHANNEL_OPENING: - case SSH_CHANNEL_CONNECTING: - case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_X11_OPEN: - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n", - c->self, c->remote_name, - c->type, c->remote_id, - c->istate, buffer_len(&c->input), - c->ostate, buffer_len(&c->output), - c->rfd, c->wfd); - buffer_append(&buffer, buf, strlen(buf)); - continue; - default: - fatal("channel_open_message: bad channel type %d", c->type); - /* NOTREACHED */ - } +} + +void +channel_input_port_open(int type, u_int32_t seq, void *ctxt) +{ + Channel *c = NULL; + u_short host_port; + char *host, *originator_string; + int remote_id, sock = -1; + + remote_id = packet_get_int(); + host = packet_get_string(NULL); + host_port = packet_get_int(); + + if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) { + originator_string = packet_get_string(NULL); + } else { + originator_string = xstrdup("unknown (remote did not supply name)"); } - buffer_append(&buffer, "\0", 1); - cp = xstrdup(buffer_ptr(&buffer)); - buffer_free(&buffer); - return cp; + packet_check_eom(); + sock = channel_connect_to(host, host_port); + if (sock != -1) { + c = channel_new("connected socket", + SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0, + originator_string, 1); + c->remote_id = remote_id; + } + if (c == NULL) { + packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(remote_id); + packet_send(); + } + xfree(host); } -/* - * Initiate forwarding of connections to local port "port" through the secure - * channel to host:port from remote side. - */ -int -channel_request_local_forwarding(u_short listen_port, const char *host_to_connect, - u_short port_to_connect, int gateway_ports) + +/* -- tcp forwarding */ + +void +channel_set_af(int af) { - return channel_request_forwarding( - NULL, listen_port, - host_to_connect, port_to_connect, - gateway_ports, /*remote_fwd*/ 0); + IPv4or6 = af; } -/* - * If 'remote_fwd' is true we have a '-R style' listener for protocol 2 - * (SSH_CHANNEL_RPORT_LISTENER). - */ -int -channel_request_forwarding( - const char *listen_address, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, - int gateway_ports, int remote_fwd) +static int +channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port, + const char *host_to_connect, u_short port_to_connect, int gateway_ports) { - int success, ch, sock, on = 1, ctype; + Channel *c; + int success, sock, on = 1; struct addrinfo hints, *ai, *aitop; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; const char *host; + char ntop[NI_MAXHOST], strport[NI_MAXSERV]; struct linger linger; success = 0; + host = (type == SSH_CHANNEL_RPORT_LISTENER) ? + listen_addr : host_to_connect; - if (remote_fwd) { - host = listen_address; - ctype = SSH_CHANNEL_RPORT_LISTENER; - } else { - host = host_to_connect; - ctype =SSH_CHANNEL_PORT_LISTENER; + if (host == NULL) { + error("No forward host name."); + return success; } - - if (strlen(host) > sizeof(channels[0].path) - 1) { + if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) { error("Forward host name too long."); return success; } - /* XXX listen_address is currently ignored */ /* * getaddrinfo returns a loopback address if the hostname is * set to NULL and hints.ai_flags is not AI_PASSIVE @@ -1830,7 +2039,7 @@ continue; if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("channel_request_forwarding: getnameinfo failed"); + error("channel_setup_fwd_listener: getnameinfo failed"); continue; } /* Create a port to listen for the host. */ @@ -1844,16 +2053,20 @@ * 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)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); linger.l_onoff = 1; linger.l_linger = 5; - setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)); + setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); debug("Local forwarding listening on %s port %s.", ntop, strport); /* Bind the socket to the address. */ if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { /* address can be in use ipv6 address is already bound */ - verbose("bind: %.100s", strerror(errno)); + if (!ai->ai_next) + error("bind: %.100s", strerror(errno)); + else + verbose("bind: %.100s", strerror(errno)); + close(sock); continue; } @@ -1864,21 +2077,39 @@ continue; } /* Allocate a channel number for the socket. */ - ch = channel_new("port listener", ctype, sock, sock, -1, + c = channel_new("port listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("port listener"), 1); - strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); - channels[ch].host_port = port_to_connect; - channels[ch].listening_port = listen_port; + strlcpy(c->path, host, sizeof(c->path)); + c->host_port = port_to_connect; + c->listening_port = listen_port; success = 1; } if (success == 0) - error("channel_request_forwarding: cannot listen to port: %d", + error("channel_setup_fwd_listener: cannot listen to port: %d", listen_port); freeaddrinfo(aitop); return success; } +/* protocol local port fwd, used by ssh (and sshd in v1) */ +int +channel_setup_local_fwd_listener(u_short listen_port, + const char *host_to_connect, u_short port_to_connect, int gateway_ports) +{ + return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, + NULL, listen_port, host_to_connect, port_to_connect, gateway_ports); +} + +/* protocol v2 remote port fwd, used by sshd */ +int +channel_setup_remote_fwd_listener(const char *listen_address, + u_short listen_port, int gateway_ports) +{ + return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, + listen_address, listen_port, NULL, 0, gateway_ports); +} + /* * Initiate forwarding of connections to port "port" on remote host through * the secure channel to host:port from local side. @@ -1888,7 +2119,7 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect, u_short port_to_connect) { - int payload_len, type, success = 0; + int type, success = 0; /* Record locally that connection to this host/port is permitted. */ if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) @@ -1899,7 +2130,7 @@ const char *address_to_bind = "0.0.0.0"; packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_put_cstring("tcpip-forward"); - packet_put_char(0); /* boolean: want reply */ + packet_put_char(1); /* boolean: want reply */ packet_put_cstring(address_to_bind); packet_put_int(listen_port); packet_send(); @@ -1915,7 +2146,7 @@ packet_write_wait(); /* Wait for response from the remote side. */ - type = packet_read(&payload_len); + type = packet_read(); switch (type) { case SSH_SMSG_SUCCESS: success = 1; @@ -1954,6 +2185,7 @@ hostname = packet_get_string(NULL); host_port = packet_get_int(); +#ifndef HAVE_CYGWIN /* * Check that an unprivileged user is not trying to forward a * privileged port. @@ -1961,8 +2193,9 @@ if (port < IPPORT_RESERVED && !is_root) packet_disconnect("Requested forwarding of port %d but user is not root.", port); +#endif /* Initiate forwarding */ - channel_request_local_forwarding(port, hostname, host_port, gateway_ports); + channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports); /* Free the argument string. */ xfree(hostname); @@ -1974,7 +2207,7 @@ * anyway, and the server has no way to know but to trust the client anyway. */ void -channel_permit_all_opens() +channel_permit_all_opens(void) { if (num_permitted_opens == 0) all_opens_permitted = 1; @@ -2007,7 +2240,7 @@ /* return socket to remote host, port */ -int +static int connect_to(const char *host, u_short port) { struct addrinfo hints, *ai, *aitop; @@ -2055,11 +2288,12 @@ return -1; } /* success */ + set_nodelay(sock); return sock; } int -channel_connect_by_listen_adress(u_short listen_port) +channel_connect_by_listen_address(u_short listen_port) { int i; @@ -2095,102 +2329,83 @@ return connect_to(host, port); } -/* - * 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 type, int plen, void *ctxt) -{ - u_short host_port; - char *host, *originator_string; - int remote_channel, sock = -1, newch; - - remote_channel = packet_get_int(); - host = packet_get_string(NULL); - host_port = packet_get_int(); - - if (have_hostname_in_open) { - originator_string = packet_get_string(NULL); - } else { - originator_string = xstrdup("unknown (remote did not supply name)"); - } - packet_done(); - sock = channel_connect_to(host, host_port); - if (sock != -1) { - newch = channel_allocate(SSH_CHANNEL_CONNECTING, - sock, originator_string); - channels[newch].remote_id = remote_channel; - - /*XXX delay answer? */ - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_channel); - packet_put_int(newch); - packet_send(); - } else { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_channel); - packet_send(); - } - xfree(host); -} +/* -- X11 forwarding */ /* * Creates an internet domain socket for listening for X11 connections. - * Returns a suitable value for the DISPLAY variable, or NULL if an error - * occurs. + * Returns 0 and a suitable display number for the DISPLAY variable + * stored in display_numberp , or -1 if an error occurs. */ - -#define NUM_SOCKS 10 - -char * -x11_create_display_inet(int screen_number, int x11_display_offset) +int +x11_create_display_inet(int x11_display_offset, int x11_use_localhost, + int single_connection, u_int *display_numberp) { + Channel *nc = NULL; int display_number, sock; u_short port; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, n, num_socks = 0, socks[NUM_SOCKS]; - char display[512]; - char hostname[MAXHOSTNAMELEN]; for (display_number = x11_display_offset; - display_number < MAX_DISPLAYS; - display_number++) { + display_number < MAX_DISPLAYS; + display_number++) { port = 6000 + display_number; memset(&hints, 0, sizeof(hints)); hints.ai_family = IPv4or6; - hints.ai_flags = AI_PASSIVE; /* XXX loopback only ? */ + hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { error("getaddrinfo: %.100s", gai_strerror(gaierr)); - return NULL; + return -1; } for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; sock = socket(ai->ai_family, SOCK_STREAM, 0); if (sock < 0) { - error("socket: %.100s", strerror(errno)); - return NULL; + if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) { + error("socket: %.100s", strerror(errno)); + return -1; + } else { + debug("x11_create_display_inet: Socket family %d not supported", + ai->ai_family); + continue; + } } +#ifdef IPV6_V6ONLY + if (ai->ai_family == AF_INET6) { + int on = 1; + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) + error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno)); + } +#endif if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { debug("bind port %d: %.100s", port, strerror(errno)); - shutdown(sock, SHUT_RDWR); close(sock); + + if (ai->ai_next) + continue; + for (n = 0; n < num_socks; n++) { - shutdown(socks[n], SHUT_RDWR); close(socks[n]); } num_socks = 0; break; } socks[num_socks++] = sock; +#ifndef DONT_TRY_OTHER_AF if (num_socks == NUM_SOCKS) break; +#else + if (x11_use_localhost) { + if (num_socks == NUM_SOCKS) + break; + } else { + break; + } +#endif } freeaddrinfo(aitop); if (num_socks > 0) @@ -2198,67 +2413,48 @@ } if (display_number >= MAX_DISPLAYS) { error("Failed to allocate internet-domain X11 display socket."); - return NULL; + return -1; } /* Start listening for connections on the socket. */ for (n = 0; n < num_socks; n++) { sock = socks[n]; if (listen(sock, 5) < 0) { error("listen: %.100s", strerror(errno)); - shutdown(sock, SHUT_RDWR); close(sock); - return NULL; + return -1; } } - /* Set up a suitable value for the DISPLAY variable. */ - if (gethostname(hostname, sizeof(hostname)) < 0) - fatal("gethostname: %.100s", strerror(errno)); - snprintf(display, sizeof display, "%.400s:%d.%d", hostname, - display_number, screen_number); - /* Allocate a channel for each socket. */ for (n = 0; n < num_socks; n++) { sock = socks[n]; - (void) channel_new("x11 listener", + nc = channel_new("x11 listener", SSH_CHANNEL_X11_LISTENER, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, xstrdup("X11 inet listener"), 1); + nc->single_connection = single_connection; } - /* Return a suitable value for the DISPLAY environment variable. */ - return xstrdup(display); + /* Return the display number for the DISPLAY environment variable. */ + *display_numberp = display_number; + return (0); } -#ifndef X_UNIX_PATH -#define X_UNIX_PATH "/tmp/.X11-unix/X" -#endif - -static -int +static int connect_local_xsocket(u_int 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; - snprintf(addr.sun_path, sizeof addr.sun_path, *path, dnr); - if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0) - return sock; - close(sock); - } + 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; + snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X, 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; } @@ -2293,7 +2489,7 @@ /* 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); + display); return -1; } /* Create a socket. */ @@ -2308,8 +2504,7 @@ * 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; + strlcpy(buf, display, sizeof(buf)); cp = strchr(buf, ':'); if (!cp) { error("Could not find ':' in DISPLAY: %.100s", display); @@ -2319,7 +2514,7 @@ /* 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); + display); return -1; } @@ -2355,6 +2550,7 @@ strerror(errno)); return -1; } + set_nodelay(sock); return sock; } @@ -2365,56 +2561,52 @@ */ void -x11_input_open(int type, int plen, void *ctxt) +x11_input_open(int type, u_int32_t seq, void *ctxt) { - int remote_channel, sock = 0, newch; + Channel *c = NULL; + int remote_id, sock = 0; char *remote_host; - u_int remote_len; - /* Get remote channel number. */ - remote_channel = packet_get_int(); + debug("Received X11 open request."); + + remote_id = packet_get_int(); - /* Get remote originator name. */ - if (have_hostname_in_open) { - remote_host = packet_get_string(&remote_len); - remote_len += 4; + if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) { + remote_host = packet_get_string(NULL); } else { remote_host = xstrdup("unknown (remote did not supply name)"); - remote_len = 0; } - - debug("Received X11 open request."); - packet_integrity_check(plen, 4 + remote_len, SSH_SMSG_X11_OPEN); + packet_check_eom(); /* Obtain a connection to the real X display. */ sock = x11_connect_display(); - if (sock == -1) { + if (sock != -1) { + /* Allocate a channel for this connection. */ + c = channel_new("connected x11 socket", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0, + remote_host, 1); + c->remote_id = remote_id; + c->force_drain = 1; + } + if (c == NULL) { /* Send refusal to the remote host. */ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_channel); - packet_send(); + packet_put_int(remote_id); } else { - /* Allocate a channel for this connection. */ - newch = channel_allocate( - (x11_saved_proto == NULL) ? - SSH_CHANNEL_OPEN : 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(); + packet_put_int(remote_id); + packet_put_int(c->self); } + packet_send(); } /* dummy protocol handler that denies SSH-1 requests (agent/x11) */ void -deny_input_open(int type, int plen, void *ctxt) +deny_input_open(int type, u_int32_t seq, void *ctxt) { int rchan = packet_get_int(); - switch(type){ + switch (type) { case SSH_SMSG_AGENT_OPEN: error("Warning: ssh server tried agent forwarding."); break; @@ -2422,7 +2614,7 @@ error("Warning: ssh server tried X11 forwarding."); break; default: - error("deny_input_open: type %d plen %d", type, plen); + error("deny_input_open: type %d", type); break; } error("Warning: this is probably a break in attempt by a malicious server."); @@ -2434,8 +2626,8 @@ /* * Requests forwarding of X11 connections, generates fake authentication * data, and enables authentication spoofing. + * This should be called in the client only. */ - void x11_request_forwarding_with_spoofing(int client_session_id, const char *proto, const char *data) @@ -2500,127 +2692,31 @@ xfree(new_data); } + +/* -- agent forwarding */ + /* Sends a message to the server to request authentication fd forwarding. */ void -auth_request_forwarding() +auth_request_forwarding(void) { packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING); packet_send(); packet_write_wait(); } -/* - * 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; -} - -/* removes the agent forwarding socket */ - -void -auth_sock_cleanup_proc(void *_pw) -{ - struct passwd *pw = _pw; - - if (channel_forwarded_auth_socket_name) { - temporarily_use_uid(pw); - unlink(channel_forwarded_auth_socket_name); - rmdir(channel_forwarded_auth_socket_dir); - channel_forwarded_auth_socket_name = NULL; - restore_uid(); - } -} - -/* - * This is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server. - * This starts forwarding authentication requests. - */ - -int -auth_input_request_forwarding(struct passwd * pw) -{ - int sock, newch; - struct sockaddr_un sunaddr; - - if (auth_get_socket_name() != NULL) - fatal("Protocol error: authentication forwarding requested twice."); - - /* Temporarily drop privileged uid for mkdir/bind. */ - temporarily_use_uid(pw); - - /* Allocate a buffer for the socket name, and format the name. */ - channel_forwarded_auth_socket_name = xmalloc(MAX_SOCKET_NAME); - channel_forwarded_auth_socket_dir = xmalloc(MAX_SOCKET_NAME); - strlcpy(channel_forwarded_auth_socket_dir, "/tmp/ssh-XXXXXXXX", MAX_SOCKET_NAME); - - /* Create private directory for socket */ - if (mkdtemp(channel_forwarded_auth_socket_dir) == NULL) { - packet_send_debug("Agent forwarding disabled: mkdtemp() failed: %.100s", - strerror(errno)); - restore_uid(); - xfree(channel_forwarded_auth_socket_name); - xfree(channel_forwarded_auth_socket_dir); - channel_forwarded_auth_socket_name = NULL; - channel_forwarded_auth_socket_dir = NULL; - return 0; - } - snprintf(channel_forwarded_auth_socket_name, MAX_SOCKET_NAME, "%s/agent.%d", - channel_forwarded_auth_socket_dir, (int) getpid()); - - /* delete agent socket on fatal() */ - fatal_add_cleanup(auth_sock_cleanup_proc, pw); - - /* 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)); - - if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) - packet_disconnect("bind: %.100s", strerror(errno)); - - /* Restore the privileged uid. */ - restore_uid(); - - /* 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_new("auth socket", - SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, - 0, xstrdup("auth socket"), 1); - - strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, - sizeof(channels[newch].path)); - return 1; -} - /* This is called to process an SSH_SMSG_AGENT_OPEN message. */ void -auth_input_open_request(int type, int plen, void *ctxt) +auth_input_open_request(int type, u_int32_t seq, void *ctxt) { - int remch, sock, newch; - char *dummyname; - - packet_integrity_check(plen, 4, type); + Channel *c = NULL; + int remote_id, sock; + char *name; /* Read the remote channel number from the message. */ - remch = packet_get_int(); + remote_id = packet_get_int(); + packet_check_eom(); /* * Get a connection to the local authentication agent (this may again @@ -2634,129 +2730,22 @@ * because authentication forwarding is only enabled if we have an * agent. */ - if (sock < 0) { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remch); - packet_send(); - 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"); - - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname); - channels[newch].remote_id = remch; - - /* Send a confirmation to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remch); - packet_put_int(newch); - packet_send(); -} - -void -channel_start_open(int id) -{ - Channel *c = channel_lookup(id); - if (c == NULL) { - log("channel_open: %d: bad id", id); - return; - } - debug("send channel open %d", id); - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring(c->ctype); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); -} -void -channel_open(int id) -{ - /* XXX REMOVE ME */ - channel_start_open(id); - packet_send(); -} -void -channel_request(int id, char *service, int wantconfirm) -{ - channel_request_start(id, service, wantconfirm); - packet_send(); - debug("channel request %d: %s", id, service) ; -} -void -channel_request_start(int id, char *service, int wantconfirm) -{ - Channel *c = channel_lookup(id); - if (c == NULL) { - log("channel_request: %d: bad id", id); - return; - } - packet_start(SSH2_MSG_CHANNEL_REQUEST); - packet_put_int(c->remote_id); - packet_put_cstring(service); - packet_put_char(wantconfirm); -} -void -channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg) -{ - Channel *c = channel_lookup(id); - if (c == NULL) { - log("channel_register_callback: %d: bad id", id); - return; - } - c->cb_event = mtype; - c->cb_fn = fn; - c->cb_arg = arg; -} -void -channel_register_cleanup(int id, channel_callback_fn *fn) -{ - Channel *c = channel_lookup(id); - if (c == NULL) { - log("channel_register_cleanup: %d: bad id", id); - return; - } - c->dettach_user = fn; -} -void -channel_cancel_cleanup(int id) -{ - Channel *c = channel_lookup(id); - if (c == NULL) { - log("channel_cancel_cleanup: %d: bad id", id); - return; + if (sock >= 0) { + name = xstrdup("authentication agent connection"); + c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, + -1, 0, 0, 0, name, 1); + c->remote_id = remote_id; + c->force_drain = 1; } - c->dettach_user = NULL; -} -void -channel_register_filter(int id, channel_filter_fn *fn) -{ - Channel *c = channel_lookup(id); if (c == NULL) { - log("channel_register_filter: %d: bad id", id); - return; + packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(remote_id); + } else { + /* Send a confirmation to the remote host. */ + debug("Forwarding authentication connection."); + packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(remote_id); + packet_put_int(c->self); } - c->input_filter = fn; -} - -void -channel_set_fds(int id, int rfd, int wfd, int efd, - int extusage, int nonblock) -{ - Channel *c = channel_lookup(id); - if (c == NULL || c->type != SSH_CHANNEL_LARVAL) - fatal("channel_activate for non-larval channel %d.", id); - channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); - c->type = SSH_CHANNEL_OPEN; - /* XXX window size? */ - c->local_window = c->local_window_max = c->local_maxpacket * 2; - packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); - packet_put_int(c->remote_id); - packet_put_int(c->local_window); packet_send(); } Index: src/crypto/openssh/channels.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/channels.h,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 channels.h --- src/crypto/openssh/channels.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/channels.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,6 @@ +/* $OpenBSD: channels.h,v 1.70 2002/06/24 14:33:27 markus Exp $ */ +/* $FreeBSD: src/crypto/openssh/channels.h,v 1.8 2002/06/29 11:48:58 des Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,7 +13,7 @@ * called by a name other than "ssh" or "Secure Shell". */ /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,16 +35,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: channels.h,v 1.31 2001/04/13 22:46:53 beck Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/channels.h,v 1.1.1.1.2.5 2001/09/28 01:33:33 green Exp $"); */ -#ifndef CHANNELS_H -#define CHANNELS_H +#ifndef CHANNEL_H +#define CHANNEL_H #include "buffer.h" /* 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 */ @@ -55,57 +55,56 @@ #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ #define SSH_CHANNEL_CONNECTING 12 #define SSH_CHANNEL_DYNAMIC 13 -#define SSH_CHANNEL_MAX_TYPE 14 +#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */ +#define SSH_CHANNEL_MAX_TYPE 15 + +#define SSH_CHANNEL_PATH_LEN 256 -/* - * Data structure for channel data. This is iniailized in channel_allocate - * and cleared in channel_free. - */ struct Channel; typedef struct Channel Channel; -typedef void channel_callback_fn(int id, void *arg); -typedef int channel_filter_fn(struct Channel *c, char *buf, int len); +typedef void channel_callback_fn(int, void *); +typedef int channel_filter_fn(struct Channel *, char *, int); struct Channel { int type; /* channel type/state */ int self; /* my own channel identifier */ int remote_id; /* channel identifier for remote peer */ - /* peer can be reached over encrypted connection, via packet-sent */ - int istate; /* input from channel (state of receive half) */ - int ostate; /* output to channel (state of transmit half) */ + u_int istate; /* input from channel (state of receive half) */ + u_int ostate; /* output to channel (state of transmit half) */ int flags; /* close sent/rcvd */ int rfd; /* read fd */ int wfd; /* write fd */ int efd; /* extended fd */ int sock; /* sock fd */ int isatty; /* rfd is a tty */ + int force_drain; /* force close on iEOF */ + int delayed; /* fdset hack */ Buffer input; /* data read from socket, to be sent over * encrypted connection */ Buffer output; /* data received over encrypted connection for * send on socket */ Buffer extended; - char path[200]; /* path for unix domain sockets, or host name - * for forwards */ + char path[SSH_CHANNEL_PATH_LEN]; + /* path for unix domain sockets, or host name for forwards */ int listening_port; /* port being listened for forwards */ int host_port; /* remote port to connect for forwards */ char *remote_name; /* remote hostname */ - int remote_window; - int remote_maxpacket; - int local_window; - int local_window_max; - int local_consumed; - int local_maxpacket; + u_int remote_window; + u_int remote_maxpacket; + u_int local_window; + u_int local_window_max; + u_int local_consumed; + u_int local_maxpacket; int extended_usage; + int single_connection; char *ctype; /* type */ /* callback */ - channel_callback_fn *cb_fn; - void *cb_arg; - int cb_event; - channel_callback_fn *dettach_user; + channel_callback_fn *confirm; + channel_callback_fn *detach_user; /* filter */ channel_filter_fn *input_filter; @@ -116,199 +115,120 @@ #define CHAN_EXTENDED_WRITE 2 /* default window/packet sizes for tcp/x11-fwd-channel */ -#define CHAN_SES_WINDOW_DEFAULT (32*1024) -#define CHAN_SES_PACKET_DEFAULT (CHAN_SES_WINDOW_DEFAULT/2) -#define CHAN_TCP_WINDOW_DEFAULT (32*1024) -#define CHAN_TCP_PACKET_DEFAULT (CHAN_TCP_WINDOW_DEFAULT/2) -#define CHAN_X11_WINDOW_DEFAULT (4*1024) -#define CHAN_X11_PACKET_DEFAULT (CHAN_X11_WINDOW_DEFAULT/2) - - -void channel_open(int id); -void channel_request(int id, char *service, int wantconfirm); -void channel_request_start(int id, char *service, int wantconfirm); -void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg); -void channel_register_cleanup(int id, channel_callback_fn *fn); -void channel_register_filter(int id, channel_filter_fn *fn); -void channel_cancel_cleanup(int id); -Channel *channel_lookup(int id); - -int -channel_new(char *ctype, int type, int rfd, int wfd, int efd, - int window, int maxpack, int extended_usage, char *remote_name, - int nonblock); -void -channel_set_fds(int id, int rfd, int wfd, int efd, - int extusage, int nonblock); - -void deny_input_open(int type, int plen, void *ctxt); - -void channel_input_channel_request(int type, int plen, void *ctxt); -void channel_input_close(int type, int plen, void *ctxt); -void channel_input_close_confirmation(int type, int plen, void *ctxt); -void channel_input_data(int type, int plen, void *ctxt); -void channel_input_extended_data(int type, int plen, void *ctxt); -void channel_input_ieof(int type, int plen, void *ctxt); -void channel_input_oclose(int type, int plen, void *ctxt); -void channel_input_open_confirmation(int type, int plen, void *ctxt); -void channel_input_open_failure(int type, int plen, void *ctxt); -void channel_input_port_open(int type, int plen, void *ctxt); -void channel_input_window_adjust(int type, int plen, void *ctxt); - -/* 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); - -/* - * Allocate/update select bitmasks and add any bits relevant to channels in - * select bitmasks. - */ -void -channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, - int rekeying); - -/* - * 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); - -/* Returns true if no channel has too much buffered data. */ -int channel_not_very_much_buffered_data(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 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. - */ -int -channel_request_local_forwarding(u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports); -int -channel_request_forwarding(const char *listen_address, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports, - int remote_fwd); - -/* - * 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(u_short port, const char *host, - u_short remote_port); - -/* - * Permits opening to any host/port if permitted_opens[] is empty. 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); - -/* Add host/port to list of allowed targets for port forwarding */ -void channel_add_permitted_opens(char *host, int port); - -/* Flush list */ -void channel_clear_permitted_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, int gateway_ports); - -/* - * 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, int x11_display_offset); - -/* - * 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 type, int plen, void *ctxt); - -/* - * 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(int client_session_id, - const char *proto, const char *data); - -/* Sends a message to the server to request authentication fd forwarding. */ -void auth_request_forwarding(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 is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server. - * This starts forwarding authentication requests. - */ -int auth_input_request_forwarding(struct passwd * pw); - -/* This is called to process an SSH_SMSG_AGENT_OPEN message. */ -void auth_input_open_request(int type, int plen, void *ctxt); - -/* XXX */ -void auth_sock_cleanup_proc(void *pw); -int channel_connect_to(const char *host, u_short host_port); -int channel_connect_by_listen_adress(u_short listen_port); -int x11_connect_display(void); - -int channel_find_open(void); +#define CHAN_SES_PACKET_DEFAULT (32*1024) +#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) +#define CHAN_TCP_PACKET_DEFAULT (32*1024) +#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) +#define CHAN_X11_PACKET_DEFAULT (16*1024) +#define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) + +/* possible input states */ +#define CHAN_INPUT_OPEN 0 +#define CHAN_INPUT_WAIT_DRAIN 1 +#define CHAN_INPUT_WAIT_OCLOSE 2 +#define CHAN_INPUT_CLOSED 3 + +/* possible output states */ +#define CHAN_OUTPUT_OPEN 0 +#define CHAN_OUTPUT_WAIT_DRAIN 1 +#define CHAN_OUTPUT_WAIT_IEOF 2 +#define CHAN_OUTPUT_CLOSED 3 + +#define CHAN_CLOSE_SENT 0x01 +#define CHAN_CLOSE_RCVD 0x02 +#define CHAN_EOF_SENT 0x04 +#define CHAN_EOF_RCVD 0x08 + +/* check whether 'efd' is still in use */ +#define CHANNEL_EFD_INPUT_ACTIVE(c) \ + (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \ + (c->efd != -1 || \ + buffer_len(&c->extended) > 0)) +#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ + (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \ + ((c->efd != -1 && !(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD))) || \ + buffer_len(&c->extended) > 0)) + +/* channel management */ + +Channel *channel_lookup(int); +Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int); +void channel_set_fds(int, int, int, int, int, int, u_int); +void channel_free(Channel *); +void channel_free_all(void); +void channel_stop_listening(void); + +void channel_send_open(int); +void channel_request_start(int, char *, int); +void channel_register_cleanup(int, channel_callback_fn *); +void channel_register_confirm(int, channel_callback_fn *); +void channel_register_filter(int, channel_filter_fn *); +void channel_cancel_cleanup(int); +int channel_close_fd(int *); + +/* protocol handler */ + +void channel_input_close(int, u_int32_t, void *); +void channel_input_close_confirmation(int, u_int32_t, void *); +void channel_input_data(int, u_int32_t, void *); +void channel_input_extended_data(int, u_int32_t, void *); +void channel_input_ieof(int, u_int32_t, void *); +void channel_input_oclose(int, u_int32_t, void *); +void channel_input_open_confirmation(int, u_int32_t, void *); +void channel_input_open_failure(int, u_int32_t, void *); +void channel_input_port_open(int, u_int32_t, void *); +void channel_input_window_adjust(int, u_int32_t, void *); + +/* file descriptor handling (read/write) */ + +void channel_prepare_select(fd_set **, fd_set **, int *, int*, int); +void channel_after_select(fd_set *, fd_set *); +void channel_output_poll(void); + +int channel_not_very_much_buffered_data(void); +void channel_close_all(void); +int channel_still_open(void); +char *channel_open_message(void); +int channel_find_open(void); + +/* tcp forwarding */ +void channel_set_af(int af); +void channel_permit_all_opens(void); +void channel_add_permitted_opens(char *, int); +void channel_clear_permitted_opens(void); +void channel_input_port_forward_request(int, int); +int channel_connect_to(const char *, u_short); +int channel_connect_by_listen_address(u_short); +void channel_request_remote_forwarding(u_short, const char *, u_short); +int channel_setup_local_fwd_listener(u_short, const char *, u_short, int); +int channel_setup_remote_fwd_listener(const char *, u_short, int); + +/* x11 forwarding */ + +int x11_connect_display(void); +int x11_create_display_inet(int, int, int, u_int *); +void x11_input_open(int, u_int32_t, void *); +void x11_request_forwarding_with_spoofing(int, const char *, const char *); +void deny_input_open(int, u_int32_t, void *); + +/* agent forwarding */ + +void auth_request_forwarding(void); +void auth_input_open_request(int, u_int32_t, void *); + +/* channel close */ + +int chan_is_dead(Channel *, int); +void chan_mark_dead(Channel *); + +/* channel events */ + +void chan_rcvd_oclose(Channel *); +void chan_read_failed(Channel *); +void chan_ibuf_empty(Channel *); + +void chan_rcvd_ieof(Channel *); +void chan_write_failed(Channel *); +void chan_obuf_empty(Channel *); #endif Index: src/crypto/openssh/cipher.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/cipher.c,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 cipher.c --- src/crypto/openssh/cipher.c 28 Sep 2001 01:33:33 -0000 1.2.2.4 +++ src/crypto/openssh/cipher.c 30 Jun 2002 11:37:58 -0000 @@ -11,7 +11,7 @@ * * * Copyright (c) 1999 Niels Provos. All rights reserved. - * Copyright (c) 1999,2000 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,8 +35,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.43 2001/02/04 15:32:23 stevesk Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/cipher.c,v 1.2.2.4 2001/09/28 01:33:33 green Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.60 2002/06/23 03:26:52 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/cipher.c,v 1.13 2002/06/29 11:48:58 des Exp $"); #include "xmalloc.h" #include "log.h" @@ -44,388 +44,76 @@ #include +#if OPENSSL_VERSION_NUMBER < 0x00906000L +#define SSH_OLD_EVP +#define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data) +#endif + +#if OPENSSL_VERSION_NUMBER < 0x00907000L +#include "rijndael.h" +static const EVP_CIPHER *evp_rijndael(void); +#endif +static const EVP_CIPHER *evp_ssh1_3des(void); +static const EVP_CIPHER *evp_ssh1_bf(void); + +struct Cipher { + char *name; + int number; /* for ssh1 only */ + u_int block_size; + u_int key_len; + const EVP_CIPHER *(*evptype)(void); +} ciphers[] = { + { "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null }, + { "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc }, + { "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des }, + { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf }, + + { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc }, + { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc }, + { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc }, + { "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 }, +#if OPENSSL_VERSION_NUMBER < 0x00907000L + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael }, + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, + { "rijndael-cbc@lysator.liu.se", + SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, +#else + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, EVP_aes_128_cbc }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, EVP_aes_192_cbc }, + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, + { "rijndael-cbc@lysator.liu.se", + SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, +#endif -/* no encryption */ -void -none_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ -} -void -none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ -} -void -none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - memcpy(dest, src, len); -} - -/* DES */ -void -des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - static int dowarn = 1; - if (dowarn) { - error("Warning: use of DES is strongly discouraged " - "due to cryptographic weaknesses"); - dowarn = 0; - } - des_set_key((void *)key, cc->u.des.key); -} -void -des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv)); -} -void -des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv, - DES_ENCRYPT); -} -void -des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv, - DES_DECRYPT); -} - -/* 3DES */ -void -des3_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - des_set_key((void *) key, cc->u.des3.key1); - des_set_key((void *) (key+8), cc->u.des3.key2); - des_set_key((void *) (key+16), cc->u.des3.key3); -} -void -des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2)); - memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3)); - if (iv == NULL) - return; - memcpy(cc->u.des3.iv3, (char *)iv, 8); -} -void -des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - des_ede3_cbc_encrypt(src, dest, len, - cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3, - &cc->u.des3.iv3, DES_ENCRYPT); -} -void -des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - des_ede3_cbc_encrypt(src, dest, len, - cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3, - &cc->u.des3.iv3, DES_DECRYPT); -} - -/* - * This is used by SSH1: - * - * What kind of triple 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 -des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - des_set_key((void *) key, cc->u.des3.key1); - des_set_key((void *) (key+8), cc->u.des3.key2); - if (keylen <= 16) - des_set_key((void *) key, cc->u.des3.key3); - else - des_set_key((void *) (key+16), cc->u.des3.key3); -} -void -des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - des_cblock iv1; - des_cblock *iv2 = &cc->u.des3.iv2; - des_cblock *iv3 = &cc->u.des3.iv3; - - memcpy(&iv1, iv2, 8); - - des_ncbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT); -} -void -des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - des_cblock iv1; - des_cblock *iv2 = &cc->u.des3.iv2; - des_cblock *iv3 = &cc->u.des3.iv3; - - memcpy(&iv1, iv2, 8); - - des_ncbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT); -} - -/* Blowfish */ -void -blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - BF_set_key(&cc->u.bf.key, keylen, (u_char *)key); -} -void -blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - if (iv == NULL) - memset(cc->u.bf.iv, 0, 8); - else - memcpy(cc->u.bf.iv, (char *)iv, 8); -} -void -blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv, - BF_ENCRYPT); -} -void -blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv, - BF_DECRYPT); -} - -/* - * SSH1 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 u_char *src, u_char *dst, int n) -{ - char c[4]; - - /* Process 4 bytes every lap. */ - for (n = n / 4; n > 0; n--) { - c[3] = *src++; - c[2] = *src++; - c[1] = *src++; - c[0] = *src++; - - *dst++ = c[0]; - *dst++ = c[1]; - *dst++ = c[2]; - *dst++ = c[3]; - } -} + { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } +}; -void -blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - swap_bytes(src, dest, len); - BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv, - BF_ENCRYPT); - swap_bytes(dest, dest, len); -} -void -blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - swap_bytes(src, dest, len); - BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv, - BF_DECRYPT); - swap_bytes(dest, dest, len); -} +/*--*/ -/* alleged rc4 */ -void -arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - RC4_set_key(&cc->u.rc4, keylen, (u_char *)key); -} -void -arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) +u_int +cipher_blocksize(Cipher *c) { - RC4(&cc->u.rc4, len, (u_char *)src, dest); + return (c->block_size); } -/* CAST */ -void -cast_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - CAST_set_key(&cc->u.cast.key, keylen, (u_char *) key); -} -void -cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - if (iv == NULL) - fatal("no IV for %s.", cc->cipher->name); - memcpy(cc->u.cast.iv, (char *)iv, 8); -} -void -cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv, - CAST_ENCRYPT); -} -void -cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) +u_int +cipher_keylen(Cipher *c) { - CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv, - CAST_DECRYPT); + return (c->key_len); } -/* RIJNDAEL */ - -#define RIJNDAEL_BLOCKSIZE 16 -void -rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - rijndael_set_key(&cc->u.rijndael.enc, (u4byte *)key, 8*keylen, 1); - rijndael_set_key(&cc->u.rijndael.dec, (u4byte *)key, 8*keylen, 0); -} -void -rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - if (iv == NULL) - fatal("no IV for %s.", cc->cipher->name); - memcpy((u_char *)cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE); -} -void -rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) +u_int +cipher_get_number(Cipher *c) { - rijndael_ctx *ctx = &cc->u.rijndael.enc; - u4byte *iv = cc->u.rijndael.iv; - u4byte in[4]; - u4byte *cprev, *cnow, *plain; - int i, blocks = len / RIJNDAEL_BLOCKSIZE; - if (len == 0) - return; - if (len % RIJNDAEL_BLOCKSIZE) - fatal("rijndael_cbc_encrypt: bad len %d", len); - cnow = (u4byte*) dest; - plain = (u4byte*) src; - cprev = iv; - for(i = 0; i < blocks; i++, plain+=4, cnow+=4) { - in[0] = plain[0] ^ cprev[0]; - in[1] = plain[1] ^ cprev[1]; - in[2] = plain[2] ^ cprev[2]; - in[3] = plain[3] ^ cprev[3]; - rijndael_encrypt(ctx, in, cnow); - cprev = cnow; - } - memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE); + return (c->number); } -void -rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - rijndael_ctx *ctx = &cc->u.rijndael.dec; - u4byte *iv = cc->u.rijndael.iv; - u4byte ivsaved[4]; - u4byte *cnow = (u4byte*) (src+len-RIJNDAEL_BLOCKSIZE); - u4byte *plain = (u4byte*) (dest+len-RIJNDAEL_BLOCKSIZE); - u4byte *ivp; - int i, blocks = len / RIJNDAEL_BLOCKSIZE; - if (len == 0) - return; - if (len % RIJNDAEL_BLOCKSIZE) - fatal("rijndael_cbc_decrypt: bad len %d", len); - memcpy(ivsaved, cnow, RIJNDAEL_BLOCKSIZE); - for(i = blocks; i > 0; i--, cnow-=4, plain-=4) { - rijndael_decrypt(ctx, cnow, plain); - ivp = (i == 1) ? iv : cnow-4; - plain[0] ^= ivp[0]; - plain[1] ^= ivp[1]; - plain[2] ^= ivp[2]; - plain[3] ^= ivp[3]; - } - memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE); -} - -Cipher ciphers[] = { - { "none", - SSH_CIPHER_NONE, 8, 0, - none_setkey, none_setiv, - none_crypt, none_crypt }, - { "des", - SSH_CIPHER_DES, 8, 8, - des_ssh1_setkey, des_ssh1_setiv, - des_ssh1_encrypt, des_ssh1_decrypt }, - { "3des", - SSH_CIPHER_3DES, 8, 16, - des3_ssh1_setkey, des3_setiv, - des3_ssh1_encrypt, des3_ssh1_decrypt }, - { "blowfish", - SSH_CIPHER_BLOWFISH, 8, 16, - blowfish_setkey, blowfish_setiv, - blowfish_ssh1_encrypt, blowfish_ssh1_decrypt }, - - { "3des-cbc", - SSH_CIPHER_SSH2, 8, 24, - des3_setkey, des3_setiv, - des3_cbc_encrypt, des3_cbc_decrypt }, - { "blowfish-cbc", - SSH_CIPHER_SSH2, 8, 16, - blowfish_setkey, blowfish_setiv, - blowfish_cbc_encrypt, blowfish_cbc_decrypt }, - { "cast128-cbc", - SSH_CIPHER_SSH2, 8, 16, - cast_setkey, cast_setiv, - cast_cbc_encrypt, cast_cbc_decrypt }, - { "arcfour", - SSH_CIPHER_SSH2, 8, 16, - arcfour_setkey, none_setiv, - arcfour_crypt, arcfour_crypt }, - { "aes128-cbc", - SSH_CIPHER_SSH2, 16, 16, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { "aes192-cbc", - SSH_CIPHER_SSH2, 16, 24, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { "aes256-cbc", - SSH_CIPHER_SSH2, 16, 32, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { "rijndael128-cbc", - SSH_CIPHER_SSH2, 16, 16, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { "rijndael192-cbc", - SSH_CIPHER_SSH2, 16, 24, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { "rijndael256-cbc", - SSH_CIPHER_SSH2, 16, 32, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { "rijndael-cbc@lysator.liu.se", - SSH_CIPHER_SSH2, 16, 32, - rijndael_setkey, rijndael_setiv, - rijndael_cbc_encrypt, rijndael_cbc_decrypt }, - { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL } -}; - -/*--*/ - u_int cipher_mask_ssh1(int client) { u_int mask = 0; - mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ + mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ mask |= 1 << SSH_CIPHER_BLOWFISH; if (client) { mask |= 1 << SSH_CIPHER_DES; @@ -465,7 +153,7 @@ return 0; ciphers = cp = xstrdup(names); for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; - (p = strsep(&cp, CIPHER_SEP))) { + (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); if (c == NULL || c->number != SSH_CIPHER_SSH2) { debug("bad cipher %s [%s]", p, names); @@ -504,8 +192,28 @@ void cipher_init(CipherContext *cc, Cipher *cipher, - const u_char *key, u_int keylen, const u_char *iv, u_int ivlen) + const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, + int encrypt) { + static int dowarn = 1; +#ifdef SSH_OLD_EVP + EVP_CIPHER *type; +#else + const EVP_CIPHER *type; +#endif + int klen; + + if (cipher->number == SSH_CIPHER_DES) { + if (dowarn) { + error("Warning: use of DES is strongly discouraged " + "due to cryptographic weaknesses"); + dowarn = 0; + } + if (keylen > 8) + keylen = 8; + } + cc->plaintext = (cipher->number == SSH_CIPHER_NONE); + if (keylen < cipher->key_len) fatal("cipher_init: key length %d is insufficient for %s.", keylen, cipher->name); @@ -513,24 +221,58 @@ fatal("cipher_init: iv length %d is insufficient for %s.", ivlen, cipher->name); cc->cipher = cipher; - cipher->setkey(cc, key, keylen); - cipher->setiv(cc, iv, ivlen); + + type = (*cipher->evptype)(); + + EVP_CIPHER_CTX_init(&cc->evp); +#ifdef SSH_OLD_EVP + if (type->key_len > 0 && type->key_len != keylen) { + debug("cipher_init: set keylen (%d -> %d)", + type->key_len, keylen); + type->key_len = keylen; + } + EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, + (encrypt == CIPHER_ENCRYPT)); +#else + if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, + (encrypt == CIPHER_ENCRYPT)) == 0) + fatal("cipher_init: EVP_CipherInit failed for %s", + cipher->name); + klen = EVP_CIPHER_CTX_key_length(&cc->evp); + if (klen > 0 && keylen != klen) { + debug("cipher_init: set keylen (%d -> %d)", klen, keylen); + if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) + fatal("cipher_init: set keylen failed (%d -> %d)", + klen, keylen); + } + if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) + fatal("cipher_init: EVP_CipherInit: set key failed for %s", + cipher->name); +#endif } void -cipher_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) +cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) { if (len % cc->cipher->block_size) fatal("cipher_encrypt: bad plaintext length %d", len); - cc->cipher->encrypt(cc, dest, src, len); +#ifdef SSH_OLD_EVP + EVP_Cipher(&cc->evp, dest, (u_char *)src, len); +#else + if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0) + fatal("evp_crypt: EVP_Cipher failed"); +#endif } void -cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - if (len % cc->cipher->block_size) - fatal("cipher_decrypt: bad ciphertext length %d", len); - cc->cipher->decrypt(cc, dest, src, len); +cipher_cleanup(CipherContext *cc) +{ +#ifdef SSH_OLD_EVP + EVP_CIPHER_CTX_cleanup(&cc->evp); +#else + if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) + error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); +#endif } /* @@ -540,7 +282,7 @@ void cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase) + const char *passphrase, int encrypt) { MD5_CTX md; u_char digest[16]; @@ -549,8 +291,436 @@ MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); MD5_Final(digest, &md); - cipher_init(cc, cipher, digest, 16, NULL, 0); + cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt); memset(digest, 0, sizeof(digest)); memset(&md, 0, sizeof(md)); +} + +/* Implementations for other non-EVP ciphers */ + +/* + * This is used by SSH1: + * + * What kind of triple 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. + */ +struct ssh1_3des_ctx +{ + EVP_CIPHER_CTX k1, k2, k3; +}; + +static int +ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, + int enc) +{ + struct ssh1_3des_ctx *c; + u_char *k1, *k2, *k3; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + if (key == NULL) + return (1); + if (enc == -1) + enc = ctx->encrypt; + k1 = k2 = k3 = (u_char *) key; + k2 += 8; + if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { + if (enc) + k3 += 16; + else + k1 += 16; + } + EVP_CIPHER_CTX_init(&c->k1); + EVP_CIPHER_CTX_init(&c->k2); + EVP_CIPHER_CTX_init(&c->k3); +#ifdef SSH_OLD_EVP + EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc); + EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc); + EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc); +#else + if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || + EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || + EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + return (0); + } +#endif + return (1); +} + +static int +ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len) +{ + struct ssh1_3des_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + error("ssh1_3des_cbc: no context"); + return (0); + } +#ifdef SSH_OLD_EVP + EVP_Cipher(&c->k1, dest, (u_char *)src, len); + EVP_Cipher(&c->k2, dest, dest, len); + EVP_Cipher(&c->k3, dest, dest, len); +#else + if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || + EVP_Cipher(&c->k2, dest, dest, len) == 0 || + EVP_Cipher(&c->k3, dest, dest, len) == 0) + return (0); +#endif + return (1); +} + +static int +ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct ssh1_3des_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + } + return (1); +} + +static const EVP_CIPHER * +evp_ssh1_3des(void) +{ + static EVP_CIPHER ssh1_3des; + + memset(&ssh1_3des, 0, sizeof(EVP_CIPHER)); + ssh1_3des.nid = NID_undef; + ssh1_3des.block_size = 8; + ssh1_3des.iv_len = 0; + ssh1_3des.key_len = 16; + ssh1_3des.init = ssh1_3des_init; + ssh1_3des.cleanup = ssh1_3des_cleanup; + ssh1_3des.do_cipher = ssh1_3des_cbc; +#ifndef SSH_OLD_EVP + ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; +#endif + return (&ssh1_3des); +} + +/* + * SSH1 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 u_char *src, u_char *dst, int n) +{ + u_char c[4]; + + /* Process 4 bytes every lap. */ + for (n = n / 4; n > 0; n--) { + c[3] = *src++; + c[2] = *src++; + c[1] = *src++; + c[0] = *src++; + + *dst++ = c[0]; + *dst++ = c[1]; + *dst++ = c[2]; + *dst++ = c[3]; + } +} + +static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL; + +static int +bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len) +{ + int ret; + + swap_bytes(in, out, len); + ret = (*orig_bf)(ctx, out, out, len); + swap_bytes(out, out, len); + return (ret); +} + +static const EVP_CIPHER * +evp_ssh1_bf(void) +{ + static EVP_CIPHER ssh1_bf; + + memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER)); + orig_bf = ssh1_bf.do_cipher; + ssh1_bf.nid = NID_undef; + ssh1_bf.do_cipher = bf_ssh1_cipher; + ssh1_bf.key_len = 32; + return (&ssh1_bf); +} + +#if OPENSSL_VERSION_NUMBER < 0x00907000L +/* RIJNDAEL */ +#define RIJNDAEL_BLOCKSIZE 16 +struct ssh_rijndael_ctx +{ + rijndael_ctx r_ctx; + u_char r_iv[RIJNDAEL_BLOCKSIZE]; +}; + +static int +ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, + int enc) +{ + struct ssh_rijndael_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + if (key != NULL) { + if (enc == -1) + enc = ctx->encrypt; + rijndael_set_key(&c->r_ctx, (u_char *)key, + 8*EVP_CIPHER_CTX_key_length(ctx), enc); + } + if (iv != NULL) + memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); + return (1); +} + +static int +ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, + u_int len) +{ + struct ssh_rijndael_ctx *c; + u_char buf[RIJNDAEL_BLOCKSIZE]; + u_char *cprev, *cnow, *plain, *ivp; + int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; + + if (len == 0) + return (1); + if (len % RIJNDAEL_BLOCKSIZE) + fatal("ssh_rijndael_cbc: bad len %d", len); + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + error("ssh_rijndael_cbc: no context"); + return (0); + } + if (ctx->encrypt) { + cnow = dest; + plain = (u_char *)src; + cprev = c->r_iv; + for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, + cnow+=RIJNDAEL_BLOCKSIZE) { + for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) + buf[j] = plain[j] ^ cprev[j]; + rijndael_encrypt(&c->r_ctx, buf, cnow); + cprev = cnow; + } + memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); + } else { + cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); + plain = dest+len-RIJNDAEL_BLOCKSIZE; + + memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); + for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, + plain-=RIJNDAEL_BLOCKSIZE) { + rijndael_decrypt(&c->r_ctx, cnow, plain); + ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; + for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) + plain[j] ^= ivp[j]; + } + memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); + } + return (1); +} + +static int +ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct ssh_rijndael_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { + memset(c, 0, sizeof(*c)); + xfree(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + } + return (1); +} + +static const EVP_CIPHER * +evp_rijndael(void) +{ + static EVP_CIPHER rijndal_cbc; + + memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); + rijndal_cbc.nid = NID_undef; + rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; + rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; + rijndal_cbc.key_len = 16; + rijndal_cbc.init = ssh_rijndael_init; + rijndal_cbc.cleanup = ssh_rijndael_cleanup; + rijndal_cbc.do_cipher = ssh_rijndael_cbc; +#ifndef SSH_OLD_EVP + rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_ALWAYS_CALL_INIT; +#endif + return (&rijndal_cbc); +} +#endif + +/* + * Exports an IV from the CipherContext required to export the key + * state back from the unprivileged child to the privileged parent + * process. + */ + +int +cipher_get_keyiv_len(CipherContext *cc) +{ + Cipher *c = cc->cipher; + int ivlen; + + if (c->number == SSH_CIPHER_3DES) + ivlen = 24; + else + ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); + return (ivlen); +} + +void +cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) +{ + Cipher *c = cc->cipher; + u_char *civ = NULL; + int evplen; + + switch (c->number) { + case SSH_CIPHER_SSH2: + case SSH_CIPHER_DES: + case SSH_CIPHER_BLOWFISH: + evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); + if (evplen == 0) + return; + if (evplen != len) + fatal("%s: wrong iv length %d != %d", __func__, + evplen, len); + +#if OPENSSL_VERSION_NUMBER < 0x00907000L + if (c->evptype == evp_rijndael) { + struct ssh_rijndael_ctx *aesc; + + aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); + if (aesc == NULL) + fatal("%s: no rijndael context", __func__); + civ = aesc->r_iv; + } else +#endif + { + civ = cc->evp.iv; + } + break; + case SSH_CIPHER_3DES: { + struct ssh1_3des_ctx *desc; + if (len != 24) + fatal("%s: bad 3des iv length: %d", __func__, len); + desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); + if (desc == NULL) + fatal("%s: no 3des context", __func__); + debug3("%s: Copying 3DES IV", __func__); + memcpy(iv, desc->k1.iv, 8); + memcpy(iv + 8, desc->k2.iv, 8); + memcpy(iv + 16, desc->k3.iv, 8); + return; + } + default: + fatal("%s: bad cipher %d", __func__, c->number); + } + memcpy(iv, civ, len); +} + +void +cipher_set_keyiv(CipherContext *cc, u_char *iv) +{ + Cipher *c = cc->cipher; + u_char *div = NULL; + int evplen = 0; + + switch (c->number) { + case SSH_CIPHER_SSH2: + case SSH_CIPHER_DES: + case SSH_CIPHER_BLOWFISH: + evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); + if (evplen == 0) + return; + +#if OPENSSL_VERSION_NUMBER < 0x00907000L + if (c->evptype == evp_rijndael) { + struct ssh_rijndael_ctx *aesc; + + aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp); + if (aesc == NULL) + fatal("%s: no rijndael context", __func__); + div = aesc->r_iv; + } else +#endif + { + div = cc->evp.iv; + } + break; + case SSH_CIPHER_3DES: { + struct ssh1_3des_ctx *desc; + desc = EVP_CIPHER_CTX_get_app_data(&cc->evp); + if (desc == NULL) + fatal("%s: no 3des context", __func__); + debug3("%s: Installed 3DES IV", __func__); + memcpy(desc->k1.iv, iv, 8); + memcpy(desc->k2.iv, iv + 8, 8); + memcpy(desc->k3.iv, iv + 16, 8); + return; + } + default: + fatal("%s: bad cipher %d", __func__, c->number); + } + memcpy(div, iv, evplen); +} + +#if OPENSSL_VERSION_NUMBER < 0x00907000L +#define EVP_X_STATE(evp) &(evp).c +#define EVP_X_STATE_LEN(evp) sizeof((evp).c) +#else +#define EVP_X_STATE(evp) (evp).cipher_data +#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size +#endif + +int +cipher_get_keycontext(CipherContext *cc, u_char *dat) +{ + Cipher *c = cc->cipher; + int plen = 0; + + if (c->evptype == EVP_rc4) { + plen = EVP_X_STATE_LEN(cc->evp); + if (dat == NULL) + return (plen); + memcpy(dat, EVP_X_STATE(cc->evp), plen); + } + return (plen); +} + +void +cipher_set_keycontext(CipherContext *cc, u_char *dat) +{ + Cipher *c = cc->cipher; + int plen; + + if (c->evptype == EVP_rc4) { + plen = EVP_X_STATE_LEN(cc->evp); + memcpy(EVP_X_STATE(cc->evp), dat, plen); + } } Index: src/crypto/openssh/cipher.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/cipher.h,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 cipher.h --- src/crypto/openssh/cipher.h 28 Sep 2001 01:33:33 -0000 1.2.2.4 +++ src/crypto/openssh/cipher.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: cipher.h,v 1.33 2002/03/18 17:13:15 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -32,17 +34,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: cipher.h,v 1.25 2000/12/19 23:17:56 markus Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/cipher.h,v 1.2.2.4 2001/09/28 01:33:33 green Exp $"); */ - #ifndef CIPHER_H #define CIPHER_H -#include -#include -#include -#include -#include "rijndael.h" +#include /* * Cipher types for SSH-1. New types can be added, but old types should not * be removed for compatibility. The maximum allowed value is 31. @@ -60,59 +55,37 @@ #define SSH_CIPHER_RESERVED 7 #define SSH_CIPHER_MAX 31 +#define CIPHER_ENCRYPT 1 +#define CIPHER_DECRYPT 0 + typedef struct Cipher Cipher; typedef struct CipherContext CipherContext; +struct Cipher; struct CipherContext { - union { - struct { - des_key_schedule key; - des_cblock iv; - } des; - struct { - des_key_schedule key1; - des_key_schedule key2; - des_cblock iv2; - des_key_schedule key3; - des_cblock iv3; - } des3; - struct { - struct bf_key_st key; - u_char iv[8]; - } bf; - struct { - CAST_KEY key; - u_char iv[8]; - } cast; - struct { - u4byte iv[4]; - rijndael_ctx enc; - rijndael_ctx dec; - } rijndael; - RC4_KEY rc4; - } u; + int plaintext; + EVP_CIPHER_CTX evp; Cipher *cipher; }; -struct Cipher { - char *name; - int number; /* for ssh1 only */ - u_int block_size; - u_int key_len; - void (*setkey)(CipherContext *, const u_char *, u_int); - void (*setiv)(CipherContext *, const u_char *, u_int); - void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int); - void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int); -}; - -u_int cipher_mask_ssh1(int client); -Cipher *cipher_by_name(const char *name); -Cipher *cipher_by_number(int id); -int cipher_number(const char *name); -char *cipher_name(int id); -int ciphers_valid(const char *names); -void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, const u_char *, u_int); -void cipher_encrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len); -void cipher_decrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len); -void cipher_set_key_string(CipherContext *context, Cipher *cipher, const char *passphrase); +u_int cipher_mask_ssh1(int); +Cipher *cipher_by_name(const char *); +Cipher *cipher_by_number(int); +int cipher_number(const char *); +char *cipher_name(int); +int ciphers_valid(const char *); +void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, + const u_char *, u_int, int); +void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); +void cipher_cleanup(CipherContext *); +void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); +u_int cipher_blocksize(Cipher *); +u_int cipher_keylen(Cipher *); + +u_int cipher_get_number(Cipher *); +void cipher_get_keyiv(CipherContext *, u_char *, u_int); +void cipher_set_keyiv(CipherContext *, u_char *); +int cipher_get_keyiv_len(CipherContext *); +int cipher_get_keycontext(CipherContext *, u_char *); +void cipher_set_keycontext(CipherContext *, u_char *); #endif /* CIPHER_H */ Index: src/crypto/openssh/cli.c =================================================================== RCS file: src/crypto/openssh/cli.c diff -N src/crypto/openssh/cli.c --- src/crypto/openssh/cli.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,231 +0,0 @@ -/* $OpenBSD: cli.c,v 1.11 2001/03/06 00:33:04 deraadt Exp $ */ - -/* - * Copyright (c) 2000 Markus Friedl. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -RCSID("$OpenBSD: cli.c,v 1.11 2001/03/06 00:33:04 deraadt Exp $"); - -#include "xmalloc.h" -#include "log.h" -#include "cli.h" - -#include - -static int cli_input = -1; -static int cli_output = -1; -static int cli_from_stdin = 0; - -sigset_t oset; -sigset_t nset; -struct sigaction nsa; -struct sigaction osa; -struct termios ntio; -struct termios otio; -int echo_modified; - -volatile int intr; - -static int -cli_open(int from_stdin) -{ - if (cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin) - return 1; - - if (from_stdin) { - if (!cli_from_stdin && cli_input >= 0) { - (void)close(cli_input); - } - cli_input = STDIN_FILENO; - cli_output = STDERR_FILENO; - } else { - cli_input = cli_output = open(_PATH_TTY, O_RDWR); - if (cli_input < 0) - fatal("You have no controlling tty. Cannot read passphrase."); - } - - cli_from_stdin = from_stdin; - - return cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin; -} - -static void -cli_close(void) -{ - if (!cli_from_stdin && cli_input >= 0) - close(cli_input); - cli_input = -1; - cli_output = -1; - cli_from_stdin = 0; - return; -} - -void -intrcatch(int sig) -{ - intr = 1; -} - -static void -cli_echo_disable(void) -{ - sigemptyset(&nset); - sigaddset(&nset, SIGTSTP); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - - intr = 0; - - memset(&nsa, 0, sizeof(nsa)); - nsa.sa_handler = intrcatch; - (void) sigaction(SIGINT, &nsa, &osa); - - echo_modified = 0; - if (tcgetattr(cli_input, &otio) == 0 && (otio.c_lflag & ECHO)) { - echo_modified = 1; - ntio = otio; - ntio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); - (void) tcsetattr(cli_input, TCSANOW, &ntio); - } - return; -} - -static void -cli_echo_restore(void) -{ - if (echo_modified != 0) { - tcsetattr(cli_input, TCSANOW, &otio); - echo_modified = 0; - } - - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - (void) sigaction(SIGINT, &osa, NULL); - - if (intr != 0) { - kill(getpid(), SIGINT); - sigemptyset(&nset); - /* XXX tty has not neccessarily drained by now? */ - sigsuspend(&nset); - intr = 0; - } - return; -} - -static int -cli_read(char* buf, int size, int echo) -{ - char ch = 0; - int i = 0; - int n; - - if (!echo) - cli_echo_disable(); - - while (ch != '\n') { - n = read(cli_input, &ch, 1); - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - continue; - if (n != 1) - break; - if (ch == '\n' || intr != 0) - break; - if (i < size) - buf[i++] = ch; - } - buf[i] = '\0'; - - if (!echo) - cli_echo_restore(); - if (!intr && !echo) - (void) write(cli_output, "\n", 1); - return i; -} - -static int -cli_write(char* buf, int size) -{ - int i, len, pos, ret = 0; - char *output, *p; - - output = xmalloc(4*size); - for (p = output, i = 0; i < size; i++) { - if (buf[i] == '\n' || buf[i] == '\r') - *p++ = buf[i]; - else - p = vis(p, buf[i], 0, 0); - } - len = p - output; - - for (pos = 0; pos < len; pos += ret) { - ret = write(cli_output, output + pos, len - pos); - if (ret == -1) { - xfree(output); - return -1; - } - } - xfree(output); - return 0; -} - -/* - * Presents a prompt and returns the response allocated with xmalloc(). - * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo - * of response depending on arg. Tries to ensure that no other userland - * buffer is storing the response. - */ -char* -cli_read_passphrase(char* prompt, int from_stdin, int echo_enable) -{ - char buf[BUFSIZ]; - char* p; - - if (!cli_open(from_stdin)) - fatal("Cannot read passphrase."); - - fflush(stdout); - - cli_write(prompt, strlen(prompt)); - cli_read(buf, sizeof buf, echo_enable); - - cli_close(); - - p = xstrdup(buf); - memset(buf, 0, sizeof(buf)); - return (p); -} - -char* -cli_prompt(char* prompt, int echo_enable) -{ - return cli_read_passphrase(prompt, 0, echo_enable); -} - -void -cli_mesg(char* mesg) -{ - cli_open(0); - cli_write(mesg, strlen(mesg)); - cli_write("\n", strlen("\n")); - cli_close(); - return; -} Index: src/crypto/openssh/cli.h =================================================================== RCS file: src/crypto/openssh/cli.h diff -N src/crypto/openssh/cli.h --- src/crypto/openssh/cli.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,42 +0,0 @@ -/* $OpenBSD: cli.h,v 1.4 2001/03/01 03:38:33 deraadt Exp $ */ - -/* - * Copyright (c) 2000 Markus Friedl. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $OpenBSD: cli.h,v 1.4 2001/03/01 03:38:33 deraadt Exp $ */ - -#ifndef CLI_H -#define CLI_H - -/* - * Presents a prompt and returns the response allocated with xmalloc(). - * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo - * of response depending on arg. Tries to ensure that no other userland - * buffer is storing the response. - */ -char * cli_read_passphrase(char * prompt, int from_stdin, int echo_enable); -char * cli_prompt(char * prompt, int echo_enable); -void cli_mesg(char * mesg); - -#endif /* CLI_H */ Index: src/crypto/openssh/clientloop.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/clientloop.c,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 clientloop.c --- src/crypto/openssh/clientloop.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/clientloop.c 30 Jun 2002 11:37:58 -0000 @@ -35,7 +35,7 @@ * * * SSH2 support added by Markus Friedl. - * Copyright (c) 1999,2000 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.65 2001/04/20 07:17:51 djm Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.102 2002/06/24 14:33:27 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -81,6 +81,7 @@ #include "atomicio.h" #include "sshtty.h" #include "misc.h" +#include "readpass.h" /* import options */ extern Options options; @@ -101,7 +102,8 @@ * 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; +static volatile sig_atomic_t received_window_change_signal = 0; +static volatile sig_atomic_t received_signal = 0; /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ static int in_non_blocking_mode = 0; @@ -123,7 +125,7 @@ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ static int session_closed = 0; /* In SSH2: login session closed. */ -void client_init_dispatch(void); +static void client_init_dispatch(void); int session_ident = -1; /*XXX*/ @@ -131,7 +133,7 @@ /* Restores stdin to blocking mode. */ -void +static void leave_non_blocking(void) { if (in_non_blocking_mode) { @@ -143,7 +145,7 @@ /* Puts stdin terminal in non-blocking mode. */ -void +static void enter_non_blocking(void) { in_non_blocking_mode = 1; @@ -156,7 +158,7 @@ * flag indicating that the window has changed. */ -void +static void window_change_handler(int sig) { received_window_change_signal = 1; @@ -168,16 +170,11 @@ * signals must be trapped to restore terminal modes. */ -void +static void 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); + received_signal = sig; + quit_pending = 1; } /* @@ -185,7 +182,7 @@ * available resolution. */ -double +static double get_current_time(void) { struct timeval tv; @@ -199,7 +196,7 @@ * not appear to wake up when redirecting from /dev/null. */ -void +static void client_check_initial_eof_on_stdin(void) { int len; @@ -251,14 +248,14 @@ * connection. */ -void +static void client_make_packets_from_stdin_data(void) { u_int len; /* Send buffered stdin data to the server. */ while (buffer_len(&stdin_buffer) > 0 && - packet_not_very_much_data_to_write()) { + packet_not_very_much_data_to_write()) { len = buffer_len(&stdin_buffer); /* Keep the packets at reasonable size. */ if (len > packet_get_maxsize()) @@ -283,7 +280,7 @@ * appropriate. */ -void +static void client_check_window_change(void) { struct winsize ws; @@ -320,12 +317,12 @@ * one of the file descriptors). */ -void +static void client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, - int *maxfdp, int rekeying) + int *maxfdp, int *nallocp, int rekeying) { /* Add any selections by the channel mechanism. */ - channel_prepare_select(readsetp, writesetp, maxfdp, rekeying); + channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying); if (!compat20) { /* Read from the connection, unless our buffers are full. */ @@ -346,7 +343,16 @@ if (buffer_len(&stderr_buffer) > 0) FD_SET(fileno(stderr), *writesetp); } else { - FD_SET(connection_in, *readsetp); + /* channel_prepare_select could have closed the last channel */ + if (session_closed && !channel_still_open() && + !packet_have_data_to_write()) { + /* clear mask since we did not call select() */ + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); + return; + } else { + FD_SET(connection_in, *readsetp); + } } /* Select server connection if have data to write to the server. */ @@ -370,8 +376,8 @@ * We have to return, because the mainloop checks for the flags * set by the signal handlers. */ - memset(*readsetp, 0, *maxfdp); - memset(*writesetp, 0, *maxfdp); + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); if (errno == EINTR) return; @@ -382,7 +388,7 @@ } } -void +static void client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) { struct winsize oldws, newws; @@ -412,9 +418,9 @@ /* 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)) + oldws.ws_col != newws.ws_col || + oldws.ws_xpixel != newws.ws_xpixel || + oldws.ws_ypixel != newws.ws_ypixel)) received_window_change_signal = 1; /* OK, we have been continued by the user. Reinitialize buffers. */ @@ -425,7 +431,7 @@ enter_raw_mode(); } -void +static void client_process_net_input(fd_set * readset) { int len; @@ -465,8 +471,69 @@ } } +static void +process_cmdline(void) +{ + void (*handler)(int); + char *s, *cmd; + u_short fwd_port, fwd_host_port; + char buf[1024], sfwd_port[6], sfwd_host_port[6]; + int local = 0; + + leave_raw_mode(); + handler = signal(SIGINT, SIG_IGN); + cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); + if (s == NULL) + goto out; + while (*s && isspace(*s)) + s++; + if (*s == 0) + goto out; + if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) { + log("Invalid command."); + goto out; + } + if (s[1] == 'L') + local = 1; + if (!local && !compat20) { + log("Not supported for SSH protocol version 1."); + goto out; + } + s += 2; + while (*s && isspace(*s)) + s++; + + if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", + sfwd_port, buf, sfwd_host_port) != 3 && + sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", + sfwd_port, buf, sfwd_host_port) != 3) { + log("Bad forwarding specification."); + goto out; + } + if ((fwd_port = a2port(sfwd_port)) == 0 || + (fwd_host_port = a2port(sfwd_host_port)) == 0) { + log("Bad forwarding port(s)."); + goto out; + } + if (local) { + if (channel_setup_local_fwd_listener(fwd_port, buf, + fwd_host_port, options.gateway_ports) < 0) { + log("Port forwarding failed."); + goto out; + } + } else + channel_request_remote_forwarding(fwd_port, buf, + fwd_host_port); + log("Forwarding port."); +out: + signal(SIGINT, handler); + enter_raw_mode(); + if (cmd) + xfree(cmd); +} + /* process the characters one by one */ -int +static int process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) { char string[1024]; @@ -517,36 +584,19 @@ continue; case '&': - /* XXX does not work yet with proto 2 */ - if (compat20) - continue; /* * 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(bin) == 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); + snprintf(string, sizeof string, + "%c& [backgrounded]\n", escape_char); + buffer_append(berr, string, strlen(string)); /* Fork into background. */ pid = fork(); @@ -559,14 +609,35 @@ exit(0); } /* The child continues serving connections. */ - continue; /*XXX ? */ + if (compat20) { + buffer_append(bin, "\004", 1); + /* fake EOF on stdin */ + return -1; + } else 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(bin) == 0) { + packet_start(SSH_CMSG_EOF); + packet_send(); + } + } + continue; case '?': snprintf(string, sizeof string, "%c?\r\n\ Supported escape sequences:\r\n\ ~. - terminate connection\r\n\ -~R - Request rekey (SSH protocol 2 only)\r\n\ +~C - open a command line\r\n\ +~R - Request rekey (SSH protocol 2 only)\r\n\ ~^Z - suspend ssh\r\n\ ~# - list forwarded connections\r\n\ ~& - background ssh (when waiting for connections to terminate)\r\n\ @@ -585,6 +656,10 @@ xfree(s); continue; + case 'C': + process_cmdline(); + continue; + default: if (ch != escape_char) { buffer_put_char(bin, escape_char); @@ -616,7 +691,7 @@ return bytes; } -void +static void client_process_input(fd_set * readset) { int len; @@ -651,7 +726,7 @@ packet_start(SSH_CMSG_EOF); packet_send(); } - } else if (escape_char == -1) { + } else if (escape_char == SSH_ESCAPECHAR_NONE) { /* * Normal successful read, and no escape character. * Just append the data to buffer. @@ -669,7 +744,7 @@ } } -void +static void client_process_output(fd_set * writeset) { int len; @@ -730,7 +805,7 @@ * preparatory phase. */ -void +static void client_process_buffered_input_packets(void) { dispatch_run(DISPATCH_NONBLOCK, &quit_pending, compat20 ? xxx_kex : NULL); @@ -738,19 +813,20 @@ /* scan buf[] for '~' before sending data to the peer */ -int +static int simple_escape_filter(Channel *c, char *buf, int len) { /* XXX we assume c->extended is writeable */ return process_escapes(&c->input, &c->output, &c->extended, buf, len); } -void +static void client_channel_closed(int id, void *arg) { if (id != session_ident) error("client_channel_closed: id %d != session_ident %d", id, session_ident); + channel_cancel_cleanup(id); session_closed = 1; if (in_raw_mode()) leave_raw_mode(); @@ -759,8 +835,8 @@ /* * 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. + * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character + * used as an escape character for terminating or suspending the session. */ int @@ -768,7 +844,7 @@ { fd_set *readset = NULL, *writeset = NULL; double start_time, total_time; - int max_fd = 0, len, rekeying = 0; + int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; char buf[100]; debug("Entering interactive session."); @@ -814,7 +890,6 @@ signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); - signal(SIGPIPE, SIG_IGN); if (have_pty) signal(SIGWINCH, window_change_handler); @@ -823,7 +898,7 @@ if (compat20) { session_ident = ssh2_chan_id; - if (escape_char != -1) + if (escape_char != SSH_ESCAPECHAR_NONE) channel_register_filter(session_ident, simple_escape_filter); if (session_ident != -1) @@ -875,8 +950,9 @@ * Wait until we have something to do (something becomes * available on one of the descriptors). */ + max_fd2 = max_fd; client_wait_until_can_do_something(&readset, &writeset, - &max_fd, rekeying); + &max_fd2, &nalloc, rekeying); if (quit_pending) break; @@ -924,8 +1000,24 @@ if (have_pty) signal(SIGWINCH, SIG_DFL); - /* Stop listening for connections. */ - channel_stop_listening(); + channel_free_all(); + + if (have_pty) + leave_raw_mode(); + + /* restore blocking io */ + if (!isatty(fileno(stdin))) + unset_nonblock(fileno(stdin)); + if (!isatty(fileno(stdout))) + unset_nonblock(fileno(stdout)); + if (!isatty(fileno(stderr))) + unset_nonblock(fileno(stderr)); + + if (received_signal) { + if (in_non_blocking_mode) /* XXX */ + leave_non_blocking(); + fatal("Killed by signal %d.", (int) received_signal); + } /* * In interactive mode (with pseudo tty) display a message indicating @@ -935,6 +1027,7 @@ snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); buffer_append(&stderr_buffer, buf, strlen(buf)); } + /* Output any buffered data for stdout. */ while (buffer_len(&stdout_buffer) > 0) { len = write(fileno(stdout), buffer_ptr(&stdout_buffer), @@ -959,9 +1052,6 @@ stderr_bytes += len; } - if (have_pty) - leave_raw_mode(); - /* Clear and free any buffers. */ memset(buf, 0, sizeof(buf)); buffer_free(&stdin_buffer); @@ -971,11 +1061,11 @@ /* 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); + 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); + 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); @@ -984,31 +1074,31 @@ /*********/ -void -client_input_stdout_data(int type, int plen, void *ctxt) +static void +client_input_stdout_data(int type, u_int32_t seq, void *ctxt) { u_int data_len; char *data = packet_get_string(&data_len); - packet_integrity_check(plen, 4 + data_len, type); + packet_check_eom(); buffer_append(&stdout_buffer, data, data_len); memset(data, 0, data_len); xfree(data); } -void -client_input_stderr_data(int type, int plen, void *ctxt) +static void +client_input_stderr_data(int type, u_int32_t seq, void *ctxt) { u_int data_len; char *data = packet_get_string(&data_len); - packet_integrity_check(plen, 4 + data_len, type); + packet_check_eom(); buffer_append(&stderr_buffer, data, data_len); memset(data, 0, data_len); xfree(data); } -void -client_input_exit_status(int type, int plen, void *ctxt) +static void +client_input_exit_status(int type, u_int32_t seq, void *ctxt) { - packet_integrity_check(plen, 4, type); exit_status = packet_get_int(); + packet_check_eom(); /* Acknowledge the exit. */ packet_start(SSH_CMSG_EXIT_CONFIRMATION); packet_send(); @@ -1021,44 +1111,46 @@ quit_pending = 1; } -Channel * +static Channel * client_request_forwarded_tcpip(const char *request_type, int rchan) { Channel* c = NULL; char *listen_address, *originator_address; int listen_port, originator_port; - int sock, newch; + int sock; /* Get rest of the packet */ listen_address = packet_get_string(NULL); listen_port = packet_get_int(); originator_address = packet_get_string(NULL); originator_port = packet_get_int(); - packet_done(); + packet_check_eom(); debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", listen_address, listen_port, originator_address, originator_port); - sock = channel_connect_by_listen_adress(listen_port); - if (sock >= 0) { - newch = channel_new("forwarded-tcpip", - SSH_CHANNEL_CONNECTING, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - xstrdup(originator_address), 1); - c = channel_lookup(newch); + sock = channel_connect_by_listen_address(listen_port); + if (sock < 0) { + xfree(originator_address); + xfree(listen_address); + return NULL; } + c = channel_new("forwarded-tcpip", + SSH_CHANNEL_CONNECTING, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + xstrdup(originator_address), 1); xfree(originator_address); xfree(listen_address); return c; } -Channel* +static Channel* client_request_x11(const char *request_type, int rchan) { Channel *c = NULL; char *originator; int originator_port; - int sock, newch; + int sock; if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); @@ -1072,27 +1164,27 @@ } else { originator_port = packet_get_int(); } - packet_done(); + packet_check_eom(); /* XXX check permission */ debug("client_request_x11: request from %s %d", originator, originator_port); - sock = x11_connect_display(); - if (sock >= 0) { - newch = channel_new("x11", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, - xstrdup("x11"), 1); - c = channel_lookup(newch); - } xfree(originator); + sock = x11_connect_display(); + if (sock < 0) + return NULL; + c = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, + xstrdup("x11"), 1); + c->force_drain = 1; return c; } -Channel* +static Channel* client_request_agent(const char *request_type, int rchan) { Channel *c = NULL; - int sock, newch; + int sock; if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); @@ -1100,26 +1192,24 @@ return NULL; } sock = ssh_get_authentication_socket(); - if (sock >= 0) { - newch = channel_new("authentication agent connection", - SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - xstrdup("authentication agent connection"), 1); - c = channel_lookup(newch); - } + if (sock < 0) + return NULL; + c = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + xstrdup("authentication agent connection"), 1); + c->force_drain = 1; return c; } /* XXXX move to generic input handler */ -void -client_input_channel_open(int type, int plen, void *ctxt) +static void +client_input_channel_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; char *ctype; - u_int len; int rchan; - int rmaxpack; - int rwindow; + u_int rmaxpack, rwindow, len; ctype = packet_get_string(&len); rchan = packet_get_int(); @@ -1142,26 +1232,29 @@ c->remote_id = rchan; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; - - packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - packet_send(); + if (c->type != SSH_CHANNEL_CONNECTING) { + packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(c->remote_id); + packet_put_int(c->self); + packet_put_int(c->local_window); + packet_put_int(c->local_maxpacket); + packet_send(); + } } else { debug("failure %s", ctype); packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); packet_put_int(rchan); packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); - packet_put_cstring("bla bla"); - packet_put_cstring(""); + if (!(datafellows & SSH_BUG_OPENFAILURE)) { + packet_put_cstring("open failed"); + packet_put_cstring(""); + } packet_send(); } xfree(ctype); } -void -client_input_channel_req(int type, int plen, void *ctxt) +static void +client_input_channel_req(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; int id, reply, success = 0; @@ -1186,7 +1279,7 @@ } else if (strcmp(rtype, "exit-status") == 0) { success = 1; exit_status = packet_get_int(); - packet_done(); + packet_check_eom(); } if (reply) { packet_start(success ? @@ -1196,11 +1289,30 @@ } xfree(rtype); } +static void +client_input_global_request(int type, u_int32_t seq, void *ctxt) +{ + char *rtype; + int want_reply; + int success = 0; -void + rtype = packet_get_string(NULL); + want_reply = packet_get_char(); + debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply); + if (want_reply) { + packet_start(success ? + SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); + packet_send(); + packet_write_wait(); + } + xfree(rtype); +} + +static void client_init_dispatch_20(void) { dispatch_init(&dispatch_protocol_error); + dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); @@ -1210,11 +1322,16 @@ dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); + dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); /* rekeying */ dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); + + /* global request reply messages */ + dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); + dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); } -void +static void client_init_dispatch_13(void) { dispatch_init(NULL); @@ -1233,14 +1350,14 @@ dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? &x11_input_open : &deny_input_open); } -void +static void client_init_dispatch_15(void) { client_init_dispatch_13(); dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); } -void +static void client_init_dispatch(void) { if (compat20) Index: src/crypto/openssh/clientloop.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/clientloop.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 clientloop.h --- src/crypto/openssh/clientloop.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/clientloop.h 30 Jun 2002 11:37:58 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.4 2001/02/06 22:43:02 markus Exp $ */ +/* $OpenBSD: clientloop.h,v 1.7 2002/04/22 21:04:52 markus Exp $ */ /* * Author: Tatu Ylonen @@ -36,4 +36,5 @@ */ /* Client side main loop for the interactive session. */ -int client_loop(int have_pty, int escape_char, int id); +int client_loop(int, int, int); +void client_global_request_reply(int type, u_int32_t seq, void *ctxt); Index: src/crypto/openssh/compat.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/compat.c,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 compat.c --- src/crypto/openssh/compat.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/compat.c 30 Jun 2002 11:37:58 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999,2000 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,15 +23,14 @@ */ #include "includes.h" -RCSID("$FreeBSD: src/crypto/openssh/compat.c,v 1.1.1.1.2.5 2001/09/28 01:33:33 green Exp $"); -RCSID("$OpenBSD: compat.c,v 1.47 2001/04/18 23:43:25 markus Exp $"); - -#include +RCSID("$OpenBSD: compat.c,v 1.63 2002/04/10 08:21:47 markus Exp $"); +#include "buffer.h" #include "packet.h" #include "xmalloc.h" #include "compat.h" #include "log.h" +#include "match.h" int compat13 = 0; int compat20 = 0; @@ -53,76 +52,107 @@ void compat_datafellows(const char *version) { - int i, ret; - char ebuf[1024]; - regex_t reg; + int i; static struct { char *pat; int bugs; } check[] = { - { "^OpenSSH[-_]2\\.[012]", - SSH_OLD_SESSIONID|SSH_BUG_BANNER| - SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, - { "^OpenSSH_2\\.3\\.0", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| - SSH_OLD_DHGEX|SSH_BUG_NOREKEY}, - { "^OpenSSH_2\\.3\\.", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| - SSH_BUG_NOREKEY}, - { "^OpenSSH_2\\.5\\.[01]p1", + { "OpenSSH-2.0*," + "OpenSSH-2.1*," + "OpenSSH_2.1*," + "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| + SSH_OLD_DHGEX|SSH_BUG_NOREKEY| + SSH_BUG_EXTEOF}, + { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| + SSH_OLD_DHGEX|SSH_BUG_NOREKEY| + SSH_BUG_EXTEOF}, + { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| + SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, + { "OpenSSH_2.5.0p1*," + "OpenSSH_2.5.1p1*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| - SSH_BUG_NOREKEY }, - { "^OpenSSH_2\\.5\\.[012]", - SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, - { "^OpenSSH_2\\.5\\.3", - SSH_BUG_NOREKEY }, - { "^OpenSSH", 0 }, - { "MindTerm", 0 }, - { "^2\\.1\\.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| + SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, + { "OpenSSH_2.5.0*," + "OpenSSH_2.5.1*," + "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| + SSH_BUG_EXTEOF}, + { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, + { "OpenSSH_2.*," + "OpenSSH_3.0*," + "OpenSSH_3.1*", SSH_BUG_EXTEOF}, + { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, + { "OpenSSH*", 0 }, + { "*MindTerm*", 0 }, + { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| SSH_OLD_SESSIONID|SSH_BUG_DEBUG| SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE }, - { "^2\\.1 ", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| + { "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| SSH_OLD_SESSIONID|SSH_BUG_DEBUG| SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE }, - { "^2\\.0\\.1[3-9]", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| + { "2.0.13*," + "2.0.14*," + "2.0.15*," + "2.0.16*," + "2.0.17*," + "2.0.18*," + "2.0.19*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| SSH_OLD_SESSIONID|SSH_BUG_DEBUG| SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| SSH_BUG_PKOK|SSH_BUG_RSASIGMD5| - SSH_BUG_HBSERVICE }, - { "^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| + SSH_BUG_HBSERVICE|SSH_BUG_OPENFAILURE| + SSH_BUG_DUMMYCHAN }, + { "2.0.11*," + "2.0.12*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| + SSH_OLD_SESSIONID|SSH_BUG_DEBUG| + SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| + SSH_BUG_PKAUTH|SSH_BUG_PKOK| + SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| + SSH_BUG_DUMMYCHAN }, + { "2.0.*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| SSH_OLD_SESSIONID|SSH_BUG_DEBUG| SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| SSH_BUG_PKAUTH|SSH_BUG_PKOK| + SSH_BUG_RSASIGMD5|SSH_BUG_OPENFAILURE| + SSH_BUG_DERIVEKEY|SSH_BUG_DUMMYCHAN }, + { "2.2.0*," + "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| SSH_BUG_RSASIGMD5 }, - { "^2\\.[23]\\.0", SSH_BUG_HMAC|SSH_BUG_RSASIGMD5 }, - { "^2\\.3\\.", SSH_BUG_RSASIGMD5 }, - { "^2\\.[2-9]\\.", 0 }, - { "^2\\.4$", SSH_OLD_SESSIONID }, /* Van Dyke */ - { "^3\\.0 SecureCRT", SSH_OLD_SESSIONID }, - { "^1\\.7 SecureFX", SSH_OLD_SESSIONID }, - { "^1\\.2\\.1[89]", SSH_BUG_IGNOREMSG }, - { "^1\\.2\\.2[012]", SSH_BUG_IGNOREMSG }, - { "^1\\.3\\.2", SSH_BUG_IGNOREMSG }, /* f-secure */ - { "^SSH Compatible Server", /* Netscreen */ + { "2.3.*", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5 }, + { "2.4", SSH_OLD_SESSIONID }, /* Van Dyke */ + { "2.*", SSH_BUG_DEBUG }, + { "3.0.*", SSH_BUG_DEBUG }, + { "3.0 SecureCRT*", SSH_OLD_SESSIONID }, + { "1.7 SecureFX*", SSH_OLD_SESSIONID }, + { "1.2.18*," + "1.2.19*," + "1.2.20*," + "1.2.21*," + "1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, + { "1.3.2*", /* F-Secure */ + SSH_BUG_IGNOREMSG|SSH_BUG_K5USER }, + { "1.2.1*," + "1.2.2*," + "1.2.3*", SSH_BUG_K5USER }, + { "*SSH Compatible Server*", /* Netscreen */ SSH_BUG_PASSWORDPAD }, - { "^OSU_0", SSH_BUG_PASSWORDPAD }, - { "^OSU_1\\.[0-4]", SSH_BUG_PASSWORDPAD }, - { "^OSU_1\\.5alpha[1-3]", - SSH_BUG_PASSWORDPAD }, - { "^SSH_Version_Mapper", + { "*OSU_0*," + "OSU_1.0*," + "OSU_1.1*," + "OSU_1.2*," + "OSU_1.3*," + "OSU_1.4*," + "OSU_1.5alpha1*," + "OSU_1.5alpha2*," + "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, + { "*SSH_Version_Mapper*", SSH_BUG_SCANNER }, { NULL, 0 } }; + /* process table, return first match */ for (i = 0; check[i].pat; i++) { - ret = regcomp(®, check[i].pat, REG_EXTENDED|REG_NOSUB); - if (ret != 0) { - regerror(ret, ®, ebuf, sizeof(ebuf)); - ebuf[sizeof(ebuf)-1] = '\0'; - error("regerror: %s", ebuf); - continue; - } - ret = regexec(®, version, 0, NULL, 0); - regfree(®); - if (ret == 0) { + if (match_pattern_list(version, check[i].pat, + strlen(check[i].pat), 0) == 1) { debug("match: %s pat %s", version, check[i].pat); datafellows = check[i].bugs; return; @@ -142,7 +172,7 @@ return ret; q = s = xstrdup(spec); for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { - switch(atoi(p)) { + switch (atoi(p)) { case 1: if (ret == SSH_PROTO_UNKNOWN) ret |= SSH_PROTO_1_PREFERRED; @@ -163,24 +193,25 @@ char * compat_cipher_proposal(char *cipher_prop) { + Buffer b; char *orig_prop, *fix_ciphers; char *cp, *tmp; - size_t len; if (!(datafellows & SSH_BUG_BIGENDIANAES)) return(cipher_prop); - len = strlen(cipher_prop) + 1; - fix_ciphers = xmalloc(len); - *fix_ciphers = '\0'; + buffer_init(&b); tmp = orig_prop = xstrdup(cipher_prop); - while((cp = strsep(&tmp, ",")) != NULL) { - if (strncmp(cp, "aes", 3) && strncmp(cp, "rijndael", 8)) { - if (*fix_ciphers) - strlcat(fix_ciphers, ",", len); - strlcat(fix_ciphers, cp, len); + while ((cp = strsep(&tmp, ",")) != NULL) { + if (strncmp(cp, "aes", 3) != 0) { + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, cp, strlen(cp)); } } + buffer_append(&b, "\0", 1); + fix_ciphers = xstrdup(buffer_ptr(&b)); + buffer_free(&b); xfree(orig_prop); debug2("Original cipher proposal: %s", cipher_prop); debug2("Compat cipher proposal: %s", fix_ciphers); Index: src/crypto/openssh/compat.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/compat.h,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 compat.h --- src/crypto/openssh/compat.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/compat.h 30 Jun 2002 11:37:58 -0000 @@ -1,5 +1,7 @@ +/* $OpenBSD: compat.h,v 1.32 2002/04/10 08:21:47 markus Exp $ */ + /* - * Copyright (c) 1999 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -21,8 +23,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$FreeBSD: src/crypto/openssh/compat.h,v 1.1.1.1.2.5 2001/09/28 01:33:33 green Exp $"); */ -/* RCSID("$OpenBSD: compat.h,v 1.23 2001/04/12 19:15:24 markus Exp $"); */ #ifndef COMPAT_H #define COMPAT_H @@ -32,29 +32,35 @@ #define SSH_PROTO_1_PREFERRED 0x02 #define SSH_PROTO_2 0x04 -#define SSH_BUG_SIGBLOB 0x0001 -#define SSH_BUG_PKSERVICE 0x0002 -#define SSH_BUG_HMAC 0x0004 -#define SSH_BUG_X11FWD 0x0008 -#define SSH_OLD_SESSIONID 0x0010 -#define SSH_BUG_PKAUTH 0x0020 -#define SSH_BUG_DEBUG 0x0040 -#define SSH_BUG_BANNER 0x0080 -#define SSH_BUG_IGNOREMSG 0x0100 -#define SSH_BUG_PKOK 0x0200 -#define SSH_BUG_PASSWORDPAD 0x0400 -#define SSH_BUG_SCANNER 0x0800 -#define SSH_BUG_BIGENDIANAES 0x1000 -#define SSH_BUG_RSASIGMD5 0x2000 -#define SSH_OLD_DHGEX 0x4000 -#define SSH_BUG_NOREKEY 0x8000 -#define SSH_BUG_HBSERVICE 0x10000 - -void enable_compat13(void); -void enable_compat20(void); -void compat_datafellows(const char *s); -int proto_spec(const char *spec); -char *compat_cipher_proposal(char *cipher_prop); +#define SSH_BUG_SIGBLOB 0x00000001 +#define SSH_BUG_PKSERVICE 0x00000002 +#define SSH_BUG_HMAC 0x00000004 +#define SSH_BUG_X11FWD 0x00000008 +#define SSH_OLD_SESSIONID 0x00000010 +#define SSH_BUG_PKAUTH 0x00000020 +#define SSH_BUG_DEBUG 0x00000040 +#define SSH_BUG_BANNER 0x00000080 +#define SSH_BUG_IGNOREMSG 0x00000100 +#define SSH_BUG_PKOK 0x00000200 +#define SSH_BUG_PASSWORDPAD 0x00000400 +#define SSH_BUG_SCANNER 0x00000800 +#define SSH_BUG_BIGENDIANAES 0x00001000 +#define SSH_BUG_RSASIGMD5 0x00002000 +#define SSH_OLD_DHGEX 0x00004000 +#define SSH_BUG_NOREKEY 0x00008000 +#define SSH_BUG_HBSERVICE 0x00010000 +#define SSH_BUG_OPENFAILURE 0x00020000 +#define SSH_BUG_DERIVEKEY 0x00040000 +#define SSH_BUG_DUMMYCHAN 0x00100000 +#define SSH_BUG_EXTEOF 0x00200000 +#define SSH_BUG_K5USER 0x00400000 + +void enable_compat13(void); +void enable_compat20(void); +void compat_datafellows(const char *); +int proto_spec(const char *); +char *compat_cipher_proposal(char *); + extern int compat13; extern int compat20; extern int datafellows; Index: src/crypto/openssh/compress.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/compress.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 compress.c --- src/crypto/openssh/compress.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/compress.c 30 Jun 2002 11:37:58 -0000 @@ -12,17 +12,19 @@ */ #include "includes.h" -RCSID("$OpenBSD: compress.c,v 1.14 2001/04/05 10:39:01 markus Exp $"); +RCSID("$OpenBSD: compress.c,v 1.19 2002/03/18 17:31:54 provos Exp $"); #include "log.h" #include "buffer.h" #include "zlib.h" #include "compress.h" -static z_stream incoming_stream; -static z_stream outgoing_stream; +z_stream incoming_stream; +z_stream outgoing_stream; static int compress_init_send_called = 0; static int compress_init_recv_called = 0; +static int inflate_failed = 0; +static int deflate_failed = 0; /* * Initializes compression; level is compression level from 1 to 9 @@ -33,7 +35,7 @@ buffer_compress_init_send(int level) { if (compress_init_send_called == 1) - deflateEnd(&incoming_stream); + deflateEnd(&outgoing_stream); compress_init_send_called = 1; debug("Enabling compression at level %d.", level); if (level < 1 || level > 9) @@ -55,16 +57,16 @@ buffer_compress_uninit(void) { 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); + 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); - if (compress_init_recv_called == 1) + incoming_stream.total_out, incoming_stream.total_in, + incoming_stream.total_out == 0 ? 0.0 : + (double) incoming_stream.total_in / incoming_stream.total_out); + if (compress_init_recv_called == 1 && inflate_failed == 0) inflateEnd(&incoming_stream); - if (compress_init_send_called == 1) + if (compress_init_send_called == 1 && deflate_failed == 0) deflateEnd(&outgoing_stream); } @@ -80,7 +82,7 @@ void buffer_compress(Buffer * input_buffer, Buffer * output_buffer) { - char buf[4096]; + u_char buf[4096]; int status; /* This case is not handled below. */ @@ -88,13 +90,13 @@ return; /* Input is the contents of the input buffer. */ - outgoing_stream.next_in = (u_char *) buffer_ptr(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 = (u_char *)buf; + outgoing_stream.next_out = buf; outgoing_stream.avail_out = sizeof(buf); /* Compress as much data into the buffer as possible. */ @@ -106,6 +108,7 @@ sizeof(buf) - outgoing_stream.avail_out); break; default: + deflate_failed = 1; fatal("buffer_compress: deflate returned %d", status); /* NOTREACHED */ } @@ -124,15 +127,15 @@ void buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer) { - char buf[4096]; + u_char buf[4096]; int status; - incoming_stream.next_in = (u_char *) buffer_ptr(input_buffer); + incoming_stream.next_in = buffer_ptr(input_buffer); incoming_stream.avail_in = buffer_len(input_buffer); for (;;) { /* Set up fixed-size output buffer. */ - incoming_stream.next_out = (u_char *) buf; + incoming_stream.next_out = buf; incoming_stream.avail_out = sizeof(buf); status = inflate(&incoming_stream, Z_PARTIAL_FLUSH); @@ -149,6 +152,7 @@ */ return; default: + inflate_failed = 1; fatal("buffer_uncompress: inflate returned %d", status); /* NOTREACHED */ } Index: src/crypto/openssh/compress.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/compress.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 compress.h --- src/crypto/openssh/compress.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/compress.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: compress.h,v 1.11 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,39 +13,13 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: compress.h,v 1.8 2001/04/05 10:39:02 markus Exp $"); */ - #ifndef COMPRESS_H #define COMPRESS_H -/* - * Initializes compression; level is compression level from 1 to 9 (as in - * gzip). - */ -void buffer_compress_init_send(int level); -void buffer_compress_init_recv(void); - -/* Frees any data structures allocated by buffer_compress_init. */ -void buffer_compress_uninit(void); - -/* - * 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); +void buffer_compress_init_send(int); +void buffer_compress_init_recv(void); +void buffer_compress_uninit(void); +void buffer_compress(Buffer *, Buffer *); +void buffer_uncompress(Buffer *, Buffer *); #endif /* COMPRESS_H */ Index: src/crypto/openssh/config.guess =================================================================== RCS file: src/crypto/openssh/config.guess diff -N src/crypto/openssh/config.guess --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/config.guess 30 Jun 2002 11:37:58 -0000 @@ -0,0 +1,1327 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-01-30' + +# 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. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# 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 build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; + for c in cc gcc c89 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $dummy.c $dummy.o $dummy.rel ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +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 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + UNAME_MACHINE_ARCH=`(uname -p) 2>/dev/null` || \ + UNAME_MACHINE_ARCH=unknown + case "${UNAME_MACHINE_ARCH}" in + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-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 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + 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 <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + 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 the 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-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-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 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${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:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #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_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + 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 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${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 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $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:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | 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=${UNAME_VERSION}.${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 BSD 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 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + 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 + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + 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_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $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 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + 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 ;; + 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} | sed -e 's/\.[^.]*$/.X/' + 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/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # 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-cygwin + 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 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Export LANG=C to prevent ld from outputting information in other + # languages. + ld_supported_targets=`LANG=C; export LANG; cd /; ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # 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. + 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.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /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.*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 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # 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]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*: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.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + 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:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # 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 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000: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 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + echo i386-${UNAME_MACHINE}-nto-qnx + else + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + fi + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + 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 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#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 + 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`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%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) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# 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_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $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 + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: Index: src/crypto/openssh/config.h =================================================================== RCS file: src/crypto/openssh/config.h diff -N src/crypto/openssh/config.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/config.h 30 Jun 2002 14:03:41 -0000 @@ -0,0 +1,890 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ +/* $Id$ */ +/* $FreeBSD: src/crypto/openssh/acconfig.h,v 1.3 2002/06/29 11:48:58 des Exp $ */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +/* Generated automatically from acconfig.h by autoheader. */ +/* Please make your changes there */ + + +/* Define to a Set Process Title type if your system is */ +/* supported by bsd-setproctitle.c */ +/* #undef SPT_TYPE */ + +/* setgroups() NOOP allowed */ +/* #undef SETGROUPS_NOOP */ + +/* SCO workaround */ +/* #undef BROKEN_SYS_TERMIO_H */ + +/* Define if you have SecureWare-based protected password database */ +/* #undef HAVE_SECUREWARE */ + +/* If your header files don't define LOGIN_PROGRAM, then use this (detected) */ +/* from environment and PATH */ +#define LOGIN_PROGRAM_FALLBACK "/usr/bin/login" + +/* Define if your password has a pw_class field */ +#define HAVE_PW_CLASS_IN_PASSWD 1 + +/* Define if your password has a pw_expire field */ +#define HAVE_PW_EXPIRE_IN_PASSWD 1 + +/* Define if your password has a pw_change field */ +#define HAVE_PW_CHANGE_IN_PASSWD 1 + +/* Define if your system uses access rights style file descriptor passing */ +/* #undef HAVE_ACCRIGHTS_IN_MSGHDR */ + +/* Define if your system uses ancillary data style file descriptor passing */ +#define HAVE_CONTROL_IN_MSGHDR 1 + +/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ +/* #undef BROKEN_INET_NTOA */ + +/* Define if your system defines sys_errlist[] */ +#define HAVE_SYS_ERRLIST 1 + +/* Define if your system defines sys_nerr */ +#define HAVE_SYS_NERR 1 + +/* Define if your system choked on IP TOS setting */ +/* #undef IP_TOS_IS_BROKEN */ + +/* Define if you have the getuserattr function. */ +/* #undef HAVE_GETUSERATTR */ + +/* Work around problematic Linux PAM modules handling of PAM_TTY */ +/* #undef PAM_TTY_KLUDGE */ + +/* Use PIPES instead of a socketpair() */ +/* #undef USE_PIPES */ + +/* Define if your snprintf is busted */ +/* #undef BROKEN_SNPRINTF */ + +/* Define if you are on Cygwin */ +/* #undef HAVE_CYGWIN */ + +/* Define if you have a broken realpath. */ +/* #undef BROKEN_REALPATH */ + +/* Define if you are on NeXT */ +/* #undef HAVE_NEXT */ + +/* Define if you are on NEWS-OS */ +/* #undef HAVE_NEWS4 */ + +/* Define if you want to enable PAM support */ +#define USE_PAM 1 + +/* Define if you want to enable AIX4's authenticate function */ +/* #undef WITH_AIXAUTHENTICATE */ + +/* Define if you have/want arrays (cluster-wide session managment, not C arrays) */ +/* #undef WITH_IRIX_ARRAY */ + +/* Define if you want IRIX project management */ +/* #undef WITH_IRIX_PROJECT */ + +/* Define if you want IRIX audit trails */ +/* #undef WITH_IRIX_AUDIT */ + +/* Define if you want IRIX kernel jobs */ +/* #undef WITH_IRIX_JOBS */ + +/* Location of PRNGD/EGD random number socket */ +/* #undef PRNGD_SOCKET */ + +/* Port number of PRNGD/EGD random number socket */ +/* #undef PRNGD_PORT */ + +/* Builtin PRNG command timeout */ +#define ENTROPY_TIMEOUT_MSEC 200 + +/* non-privileged user for privilege separation */ +#define SSH_PRIVSEP_USER "sshd" + +/* Define if you want to install preformatted manpages.*/ +/* #undef MANTYPE */ + +/* Define if your ssl headers are included with #include */ +#define HAVE_OPENSSL 1 + +/* Define if you are linking against RSAref. Used only to print the right + * message at run-time. */ +/* #undef RSAREF */ + +/* struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* struct utmp and struct utmpx fields */ +#define HAVE_HOST_IN_UTMP 1 +/* #undef HAVE_HOST_IN_UTMPX */ +/* #undef HAVE_ADDR_IN_UTMP */ +/* #undef HAVE_ADDR_IN_UTMPX */ +/* #undef HAVE_ADDR_V6_IN_UTMP */ +/* #undef HAVE_ADDR_V6_IN_UTMPX */ +/* #undef HAVE_SYSLEN_IN_UTMPX */ +/* #undef HAVE_PID_IN_UTMP */ +/* #undef HAVE_TYPE_IN_UTMP */ +/* #undef HAVE_TYPE_IN_UTMPX */ +/* #undef HAVE_TV_IN_UTMP */ +/* #undef HAVE_TV_IN_UTMPX */ +/* #undef HAVE_ID_IN_UTMP */ +/* #undef HAVE_ID_IN_UTMPX */ +/* #undef HAVE_EXIT_IN_UTMP */ +#define HAVE_TIME_IN_UTMP 1 +/* #undef HAVE_TIME_IN_UTMPX */ + +/* Define if you don't want to use your system's login() call */ +/* #undef DISABLE_LOGIN */ + +/* Define if you don't want to use pututline() etc. to write [uw]tmp */ +/* #undef DISABLE_PUTUTLINE */ + +/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */ +/* #undef DISABLE_PUTUTXLINE */ + +/* Define if you don't want to use lastlog */ +/* #undef DISABLE_LASTLOG */ + +/* Define if you don't want to use utmp */ +/* #undef DISABLE_UTMP */ + +/* Define if you don't want to use utmpx */ +#define DISABLE_UTMPX 1 + +/* Define if you don't want to use wtmp */ +/* #undef DISABLE_WTMP */ + +/* Define if you don't want to use wtmpx */ +#define DISABLE_WTMPX 1 + +/* Some systems need a utmpx entry for /bin/login to work */ +/* #undef LOGIN_NEEDS_UTMPX */ + +/* Some versions of /bin/login need the TERM supplied on the commandline */ +/* #undef LOGIN_NEEDS_TERM */ + +/* Define if your login program cannot handle end of options ("--") */ +/* #undef LOGIN_NO_ENDOPT */ + +/* Define if you want to specify the path to your lastlog file */ +/* #undef CONF_LASTLOG_FILE */ + +/* Define if you want to specify the path to your utmp file */ +#define CONF_UTMP_FILE "/var/run/utmp" + +/* Define if you want to specify the path to your wtmp file */ +#define CONF_WTMP_FILE "/var/log/wtmp" + +/* Define if you want to specify the path to your utmpx file */ +/* #undef CONF_UTMPX_FILE */ + +/* Define if you want to specify the path to your wtmpx file */ +/* #undef CONF_WTMPX_FILE */ + +/* Define if you want external askpass support */ +/* #undef USE_EXTERNAL_ASKPASS */ + +/* Define if libc defines __progname */ +#define HAVE___PROGNAME 1 + +/* Define if compiler implements __FUNCTION__ */ +#define HAVE___FUNCTION__ 1 + +/* Define if compiler implements __func__ */ +#define HAVE___func__ 1 + +/* Define if you want Kerberos 5 support */ +/* #undef KRB5 */ + +/* Define this if you are using the Heimdal version of Kerberos V5 */ +/* #undef HEIMDAL */ + +/* Define if you want Kerberos 4 support */ +/* #undef KRB4 */ + +/* Define if you want AFS support */ +/* #undef AFS */ + +/* Define if you want S/Key support */ +#define SKEY 1 + +/* Define if you want OPIE support */ +#define OPIE 1 + +/* Define if you want TCP Wrappers support */ +#define LIBWRAP 1 + +/* Define if your libraries define login() */ +#define HAVE_LOGIN 1 + +/* Define if your libraries define daemon() */ +#define HAVE_DAEMON 1 + +/* Define if your libraries define getpagesize() */ +#define HAVE_GETPAGESIZE 1 + +/* Define if xauth is found in your path */ +/* #undef XAUTH_PATH */ + +/* Define if you want to allow MD5 passwords */ +/* #undef HAVE_MD5_PASSWORDS */ + +/* Define if you want to disable shadow passwords */ +/* #undef DISABLE_SHADOW */ + +/* Define if you want to use shadow password expire field */ +/* #undef HAS_SHADOW_EXPIRE */ + +/* Define if you have Digital Unix Security Integration Architecture */ +/* #undef HAVE_OSF_SIA */ + +/* Define if you have getpwanam(3) [SunOS 4.x] */ +/* #undef HAVE_GETPWANAM */ + +/* Define if you have an old version of PAM which takes only one argument */ +/* to pam_strerror */ +/* #undef HAVE_OLD_PAM */ + +/* Define if you are using Solaris-derived PAM which passes pam_messages */ +/* to the conversation function with an extra level of indirection */ +/* #undef PAM_SUN_CODEBASE */ + +/* Set this to your mail directory if you don't have maillock.h */ +#define MAIL_DIRECTORY "/var/mail" + +/* Data types */ +#define HAVE_U_INT 1 +#define HAVE_INTXX_T 1 +#define HAVE_U_INTXX_T 1 +/* #undef HAVE_UINTXX_T */ +#define HAVE_INT64_T 1 +#define HAVE_U_INT64_T 1 +#define HAVE_U_CHAR 1 +#define HAVE_SIZE_T 1 +#define HAVE_SSIZE_T 1 +#define HAVE_CLOCK_T 1 +#define HAVE_MODE_T 1 +#define HAVE_PID_T 1 +#define HAVE_SA_FAMILY_T 1 +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +#define HAVE_STRUCT_ADDRINFO 1 +#define HAVE_STRUCT_IN6_ADDR 1 +#define HAVE_STRUCT_SOCKADDR_IN6 1 + +/* Fields in struct sockaddr_storage */ +#define HAVE_SS_FAMILY_IN_SS 1 +/* #undef HAVE___SS_FAMILY_IN_SS */ + +/* Define if you have /dev/ptmx */ +/* #undef HAVE_DEV_PTMX */ + +/* Define if you have /dev/ptc */ +/* #undef HAVE_DEV_PTS_AND_PTC */ + +/* Define if you need to use IP address instead of hostname in $DISPLAY */ +/* #undef IPADDR_IN_DISPLAY */ + +/* Specify default $PATH */ +/* #undef USER_PATH */ + +/* Specify location of ssh.pid */ +#define _PATH_SSH_PIDDIR "/var/run" + +/* Use IPv4 for connection by default, IPv6 can still if explicity asked */ +/* #undef IPV4_DEFAULT */ + +/* getaddrinfo is broken (if present) */ +/* #undef BROKEN_GETADDRINFO */ + +/* Workaround more Linux IPv6 quirks */ +/* #undef DONT_TRY_OTHER_AF */ + +/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */ +/* #undef IPV4_IN_IPV6 */ + +/* Define if you have BSD auth support */ +/* #undef BSD_AUTH */ + +/* Define if X11 doesn't support AF_UNIX sockets on that system */ +/* #undef NO_X11_UNIX_SOCKETS */ + +/* Needed for SCO and NeXT */ +/* #undef BROKEN_SAVED_UIDS */ + +/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */ +#define GLOB_HAS_ALTDIRFUNC 1 + +/* Define if your system glob() function has gl_matchc options in glob_t */ +/* #undef GLOB_HAS_GL_MATCHC */ + +/* Define in your struct dirent expects you to allocate extra space for d_name */ +/* #undef BROKEN_ONE_BYTE_DIRENT_D_NAME */ + +/* Define if your getopt(3) defines and uses optreset */ +#define HAVE_GETOPT_OPTRESET 1 + +/* Define on *nto-qnx systems */ +/* #undef MISSING_NFDBITS */ + +/* Define on *nto-qnx systems */ +/* #undef MISSING_HOWMANY */ + +/* Define on *nto-qnx systems */ +/* #undef MISSING_FD_MASK */ + +/* Define if you want smartcard support */ +/* #undef SMARTCARD */ + +/* Define if you want smartcard support using sectok */ +/* #undef USE_SECTOK */ + +/* Define if you want smartcard support using OpenSC */ +/* #undef USE_OPENSC */ + +/* Define if you want to use OpenSSL's internally seeded PRNG only */ +#define OPENSSL_PRNG_ONLY 1 + +/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ +/* #undef WITH_ABBREV_NO_TTY */ + +/* Define if you want a different $PATH for the superuser */ +/* #undef SUPERUSER_PATH */ + +/* Path that unprivileged child will chroot() to in privep mode */ +/* #undef PRIVSEP_PATH */ + +/* Define if you have the `mmap' function that supports MAP_ANON|SHARED */ +#define HAVE_MMAP_ANON_SHARED 1 + +/* Define if sendmsg()/recvmsg() has problems passing file descriptors */ +/* #undef BROKEN_FD_PASSING */ + + +/* Define to 1 if the `getpgrp' function requires zero arguments. */ +#define GETPGRP_VOID 1 + +/* Define to 1 if you have the `arc4random' function. */ +#define HAVE_ARC4RANDOM 1 + +/* Define to 1 if you have the `b64_ntop' function. */ +/* #undef HAVE_B64_NTOP */ + +/* Define to 1 if you have the `bcopy' function. */ +#define HAVE_BCOPY 1 + +/* Define to 1 if you have the `bindresvport_sa' function. */ +#define HAVE_BINDRESVPORT_SA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BSTRING_H */ + +/* Define to 1 if you have the `clock' function. */ +#define HAVE_CLOCK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPT_H */ + +/* Define to 1 if you have the `dirname' function. */ +#define HAVE_DIRNAME 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ENDIAN_H */ + +/* Define to 1 if you have the `endutent' function. */ +#define HAVE_ENDUTENT 1 + +/* Define to 1 if you have the `endutxent' function. */ +/* #undef HAVE_ENDUTXENT */ + +/* Define to 1 if you have the `fchmod' function. */ +#define HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#define HAVE_FCHOWN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FLOATINGPOINT_H 1 + +/* Define to 1 if you have the `freeaddrinfo' function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the `futimes' function. */ +#define HAVE_FUTIMES 1 + +/* Define to 1 if you have the `gai_strerror' function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getgrouplist' function. */ +#define HAVE_GETGROUPLIST 1 + +/* Define to 1 if you have the `getluid' function. */ +/* #undef HAVE_GETLUID */ + +/* Define to 1 if you have the `getnameinfo' function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GETOPT_H */ + +/* Define to 1 if you have the `getpwanam' function. */ +/* #undef HAVE_GETPWANAM */ + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `getttyent' function. */ +#define HAVE_GETTTYENT 1 + +/* Define to 1 if you have the `getutent' function. */ +/* #undef HAVE_GETUTENT */ + +/* Define to 1 if you have the `getutid' function. */ +/* #undef HAVE_GETUTID */ + +/* Define to 1 if you have the `getutline' function. */ +#define HAVE_GETUTLINE 1 + +/* Define to 1 if you have the `getutxent' function. */ +/* #undef HAVE_GETUTXENT */ + +/* Define to 1 if you have the `getutxid' function. */ +/* #undef HAVE_GETUTXID */ + +/* Define to 1 if you have the `getutxline' function. */ +/* #undef HAVE_GETUTXLINE */ + +/* Define to 1 if you have the `glob' function. */ +#define HAVE_GLOB 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GLOB_H 1 + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if you have the `inet_ntoa' function. */ +#define HAVE_INET_NTOA 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `innetgr' function. */ +#define HAVE_INNETGR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LASTLOG_H */ + +/* Define to 1 if you have the `des' library (-ldes). */ +/* #undef HAVE_LIBDES */ + +/* Define to 1 if you have the `des425' library (-ldes425). */ +/* #undef HAVE_LIBDES425 */ + +/* Define to 1 if you have the `dl' library (-ldl). */ +/* #undef HAVE_LIBDL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `krb' library (-lkrb). */ +/* #undef HAVE_LIBKRB */ + +/* Define to 1 if you have the `krb4' library (-lkrb4). */ +/* #undef HAVE_LIBKRB4 */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `pam' library (-lpam). */ +#define HAVE_LIBPAM 1 + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `sectok' library (-lsectok). */ +/* #undef HAVE_LIBSECTOK */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBUTIL_H 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#define HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOGIN_CAP_H 1 + +/* Define to 1 if you have the `login_getcapbool' function. */ +#define HAVE_LOGIN_GETCAPBOOL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LOGIN_H */ + +/* Define to 1 if you have the `logout' function. */ +#define HAVE_LOGOUT 1 + +/* Define to 1 if you have the `logwtmp' function. */ +#define HAVE_LOGWTMP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MAILLOCK_H */ + +/* Define to 1 if you have the `md5_crypt' function. */ +/* #undef HAVE_MD5_CRYPT */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkdtemp' function. */ +#define HAVE_MKDTEMP 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETGROUP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_SYSTM_H 1 + +/* Define to 1 if you have the `ngetaddrinfo' function. */ +/* #undef HAVE_NGETADDRINFO */ + +/* Define to 1 if you have the `ogetaddrinfo' function. */ +/* #undef HAVE_OGETADDRINFO */ + +/* Define to 1 if you have the `openpty' function. */ +#define HAVE_OPENPTY 1 + +/* Define to 1 if you have the `pam_getenvlist' function. */ +#define HAVE_PAM_GETENVLIST 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PATHS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define to 1 if you have the `pututline' function. */ +#define HAVE_PUTUTLINE 1 + +/* Define to 1 if you have the `pututxline' function. */ +/* #undef HAVE_PUTUTXLINE */ + +/* Define to 1 if you have the `readpassphrase' function. */ +#define HAVE_READPASSPHRASE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_READPASSPHRASE_H 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define to 1 if you have the `recvmsg' function. */ +#define HAVE_RECVMSG 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_RPC_TYPES_H 1 + +/* Define to 1 if you have the `rresvport_af' function. */ +#define HAVE_RRESVPORT_AF 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SECTOK_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SECURITY_PAM_APPL_H 1 + +/* Define to 1 if you have the `sendmsg' function. */ +#define HAVE_SENDMSG 1 + +/* Define to 1 if you have the `setdtablesize' function. */ +/* #undef HAVE_SETDTABLESIZE */ + +/* Define to 1 if you have the `setegid' function. */ +#define HAVE_SETEGID 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `seteuid' function. */ +#define HAVE_SETEUID 1 + +/* Define to 1 if you have the `setgroups' function. */ +#define HAVE_SETGROUPS 1 + +/* Define to 1 if you have the `setlogin' function. */ +#define HAVE_SETLOGIN 1 + +/* Define to 1 if you have the `setluid' function. */ +/* #undef HAVE_SETLUID */ + +/* Define to 1 if you have the `setpcred' function. */ +/* #undef HAVE_SETPCRED */ + +/* Define to 1 if you have the `setproctitle' function. */ +#define HAVE_SETPROCTITLE 1 + +/* Define to 1 if you have the `setresgid' function. */ +#define HAVE_SETRESGID 1 + +/* Define to 1 if you have the `setreuid' function. */ +#define HAVE_SETREUID 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 + +/* Define to 1 if you have the `setutent' function. */ +#define HAVE_SETUTENT 1 + +/* Define to 1 if you have the `setutxent' function. */ +/* #undef HAVE_SETUTXENT */ + +/* Define to 1 if you have the `setvbuf' function. */ +#define HAVE_SETVBUF 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SHADOW_H */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `sigvec' function. */ +#define HAVE_SIGVEC 1 + +/* Define to 1 if the system has the type `sig_atomic_t'. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the `socketpair' function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcat' function. */ +#define HAVE_STRLCAT 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#define HAVE_STRLCPY 1 + +/* Define to 1 if you have the `strmode' function. */ +#define HAVE_STRMODE 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if `st_blksize' is member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BITYPES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_BSDTTY_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STROPTS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SYSMACROS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the `tcgetpgrp' function. */ +#define HAVE_TCGETPGRP 1 + +/* Define to 1 if you have the `time' function. */ +#define HAVE_TIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the `truncate' function. */ +#define HAVE_TRUNCATE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TTYENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `updwtmp' function. */ +/* #undef HAVE_UPDWTMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_USERSEC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UTIL_H */ + +/* Define to 1 if you have the `utimes' function. */ +#define HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the `utmpname' function. */ +/* #undef HAVE_UTMPNAME */ + +/* Define to 1 if you have the `utmpxname' function. */ +/* #undef HAVE_UTMPXNAME */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UTMPX_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UTMP_H 1 + +/* Define to 1 if you have the `vhangup' function. */ +/* #undef HAVE_VHANGUP */ + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `waitpid' function. */ +#define HAVE_WAITPID 1 + +/* Define to 1 if you have the `_getpty' function. */ +/* #undef HAVE__GETPTY */ + +/* Define to 1 if you have the `__b64_ntop' function. */ +#define HAVE___B64_NTOP 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* The size of a `char', as computed by sizeof. */ +#define SIZEOF_CHAR 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long int', as computed by sizeof. */ +#define SIZEOF_LONG_INT 4 + +/* The size of a `long long int', as computed by sizeof. */ +#define SIZEOF_LONG_LONG_INT 8 + +/* The size of a `short int', as computed by sizeof. */ +#define SIZEOF_SHORT_INT 2 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define as `__inline' if that's what the C compiler calls it, or to nothing + if it is not supported. */ +/* #undef inline */ + +/* type to use in place of socklen_t if not defined */ +/* #undef socklen_t */ + +/* ******************* Shouldn't need to edit below this line ************** */ + +#endif /* _CONFIG_H */ Index: src/crypto/openssh/config.sub =================================================================== RCS file: src/crypto/openssh/config.sub diff -N src/crypto/openssh/config.sub --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/config.sub 30 Jun 2002 11:37:58 -0000 @@ -0,0 +1,1362 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. + +timestamp='2001-04-20' + +# 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. + +# Please send patches to . +# +# 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. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +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 + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*) + 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 | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + 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 + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +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 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ + | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ + | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | hppa64 \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | sh[34] \ + | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp10 | pdp11 \ + | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ + | v850 | c4x \ + | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ + | pj | pjl | h8500) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65) + ;; + + # 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*86 | x86_64) + 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. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ + | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | hppa2.0n-* | hppa64-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ + | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* | mcore-* \ + | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ + | [cjt]90-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + 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) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + 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-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + 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 + ;; + [cjt]90) + basic_machine=${basic_machine}-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + 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) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + 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 + ;; + 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) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + 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 + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + 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 + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + 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) + 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) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + 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 | nexgen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-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 + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + 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 + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + 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) + 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*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + 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) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + 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 + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4) + basic_machine=sh-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + 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* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -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|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # 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*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -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*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp10-*) + os=-tops20 + ;; + 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) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + 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) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + 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 + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + 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* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: Index: src/crypto/openssh/configure.ac =================================================================== RCS file: src/crypto/openssh/configure.ac diff -N src/crypto/openssh/configure.ac --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/configure.ac 30 Jun 2002 11:37:58 -0000 @@ -0,0 +1,2492 @@ +# $Id$ +# $FreeBSD: src/crypto/openssh/configure.ac,v 1.4 2002/06/29 11:57:51 des Exp $ + +AC_INIT +AC_CONFIG_SRCDIR([ssh.c]) + +AC_CONFIG_HEADER(config.h) +AC_PROG_CC +AC_CANONICAL_HOST +AC_C_BIGENDIAN + +# Checks for programs. +AC_PROG_CPP +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_PATH_PROG(AR, ar) +AC_PATH_PROGS(PERL, perl5 perl) +AC_SUBST(PERL) +AC_PATH_PROG(ENT, ent) +AC_SUBST(ENT) +AC_PATH_PROGS(FILEPRIV, filepriv, true, /sbin:/usr/sbin) +AC_PATH_PROG(TEST_MINUS_S_SH, bash) +AC_PATH_PROG(TEST_MINUS_S_SH, ksh) +AC_PATH_PROG(TEST_MINUS_S_SH, sh) +AC_PATH_PROG(SH, sh) + +# System features +AC_SYS_LARGEFILE + +if test -z "$AR" ; then + AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***]) +fi + +# Use LOGIN_PROGRAM from environment if possible +if test ! -z "$LOGIN_PROGRAM" ; then + AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM") +else + # Search for login + AC_PATH_PROG(LOGIN_PROGRAM_FALLBACK, login) + if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then + AC_DEFINE_UNQUOTED(LOGIN_PROGRAM_FALLBACK, "$LOGIN_PROGRAM_FALLBACK") + fi +fi + +if test -z "$LD" ; then + LD=$CC +fi +AC_SUBST(LD) + +AC_C_INLINE +if test "$GCC" = "yes" || test "$GCC" = "egcs"; then + CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wno-uninitialized" +fi + +# Check for some target-specific stuff +case "$host" in +*-*-aix*) + AFS_LIBS="-lld" + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + if (test "$LD" != "gcc" && test -z "$blibpath"); then + AC_MSG_CHECKING([if linkage editor ($LD) accepts -blibpath]) + saved_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -blibpath:/usr/lib:/lib:/usr/local/lib" + AC_TRY_LINK([], + [], + [ + AC_MSG_RESULT(yes) + blibpath="/usr/lib:/lib:/usr/local/lib" + ], + [ AC_MSG_RESULT(no) ] + ) + LDFLAGS="$saved_LDFLAGS" + fi + AC_CHECK_FUNC(authenticate, [AC_DEFINE(WITH_AIXAUTHENTICATE)]) + AC_DEFINE(BROKEN_GETADDRINFO) + AC_DEFINE(BROKEN_REALPATH) + dnl AIX handles lastlog as part of its login message + AC_DEFINE(DISABLE_LASTLOG) + AC_DEFINE(LOGIN_NEEDS_UTMPX) + ;; +*-*-cygwin*) + LIBS="$LIBS /usr/lib/textmode.o" + AC_DEFINE(HAVE_CYGWIN) + AC_DEFINE(USE_PIPES) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(IPV4_DEFAULT) + AC_DEFINE(IP_TOS_IS_BROKEN) + AC_DEFINE(NO_X11_UNIX_SOCKETS) + AC_DEFINE(BROKEN_FD_PASSING) + AC_DEFINE(SETGROUPS_NOOP) + ;; +*-*-dgux*) + AC_DEFINE(IP_TOS_IS_BROKEN) + ;; +*-*-darwin*) + AC_DEFINE(BROKEN_GETADDRINFO) + ;; +*-*-hpux10.26) + if test -z "$GCC"; then + CFLAGS="$CFLAGS -Ae" + fi + CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" + IPADDR_IN_DISPLAY=yes + AC_DEFINE(HAVE_SECUREWARE) + AC_DEFINE(USE_PIPES) + AC_DEFINE(LOGIN_NO_ENDOPT) + AC_DEFINE(LOGIN_NEEDS_UTMPX) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(DISABLE_UTMP) + AC_DEFINE(SPT_TYPE,SPT_PSTAT) + LIBS="$LIBS -lxnet -lsec -lsecpw" + disable_ptmx_check=yes + ;; +*-*-hpux10*) + if test -z "$GCC"; then + CFLAGS="$CFLAGS -Ae" + fi + CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" + IPADDR_IN_DISPLAY=yes + AC_DEFINE(USE_PIPES) + AC_DEFINE(LOGIN_NO_ENDOPT) + AC_DEFINE(LOGIN_NEEDS_UTMPX) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(DISABLE_UTMP) + AC_DEFINE(SPT_TYPE,SPT_PSTAT) + LIBS="$LIBS -lxnet -lsec" + ;; +*-*-hpux11*) + CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" + IPADDR_IN_DISPLAY=yes + AC_DEFINE(PAM_SUN_CODEBASE) + AC_DEFINE(USE_PIPES) + AC_DEFINE(LOGIN_NO_ENDOPT) + AC_DEFINE(LOGIN_NEEDS_UTMPX) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(DISABLE_UTMP) + AC_DEFINE(SPT_TYPE,SPT_PSTAT) + LIBS="$LIBS -lxnet -lsec" + ;; +*-*-irix5*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS" + PATH="$PATH:/usr/etc" + AC_DEFINE(BROKEN_INET_NTOA) + AC_DEFINE(WITH_ABBREV_NO_TTY) + ;; +*-*-irix6*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS" + PATH="$PATH:/usr/etc" + AC_DEFINE(WITH_IRIX_ARRAY) + AC_DEFINE(WITH_IRIX_PROJECT) + AC_DEFINE(WITH_IRIX_AUDIT) + AC_CHECK_FUNC(jlimit_startjob, [AC_DEFINE(WITH_IRIX_JOBS)]) + AC_DEFINE(BROKEN_INET_NTOA) + AC_DEFINE(WITH_ABBREV_NO_TTY) + ;; +*-*-linux*) + no_dev_ptmx=1 + check_for_libcrypt_later=1 + AC_DEFINE(DONT_TRY_OTHER_AF) + AC_DEFINE(PAM_TTY_KLUDGE) + inet6_default_4in6=yes + ;; +mips-sony-bsd|mips-sony-newsos4) + AC_DEFINE(HAVE_NEWS4) + SONY=1 + ;; +*-*-netbsd*) + need_dash_r=1 + ;; +*-*-freebsd*) + check_for_libcrypt_later=1 + ;; +*-next-*) + conf_lastlog_location="/usr/adm/lastlog" + conf_utmp_location=/etc/utmp + conf_wtmp_location=/usr/adm/wtmp + MAIL=/usr/spool/mail + AC_DEFINE(HAVE_NEXT) + AC_DEFINE(BROKEN_REALPATH) + AC_DEFINE(USE_PIPES) + AC_DEFINE(BROKEN_SAVED_UIDS) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + CFLAGS="$CFLAGS" + ;; +*-*-solaris*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib -R/usr/local/lib" + need_dash_r=1 + AC_DEFINE(PAM_SUN_CODEBASE) + AC_DEFINE(LOGIN_NEEDS_UTMPX) + AC_DEFINE(LOGIN_NEEDS_TERM) + AC_DEFINE(PAM_TTY_KLUDGE) + # hardwire lastlog location (can't detect it on some versions) + conf_lastlog_location="/var/adm/lastlog" + AC_MSG_CHECKING(for obsolete utmp and wtmp in solaris2.x) + sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'` + if test "$sol2ver" -ge 8; then + AC_MSG_RESULT(yes) + AC_DEFINE(DISABLE_UTMP) + AC_DEFINE(DISABLE_WTMP) + else + AC_MSG_RESULT(no) + fi + ;; +*-*-sunos4*) + CPPFLAGS="$CPPFLAGS -DSUNOS4" + AC_CHECK_FUNCS(getpwanam) + AC_DEFINE(PAM_SUN_CODEBASE) + conf_utmp_location=/etc/utmp + conf_wtmp_location=/var/adm/wtmp + conf_lastlog_location=/var/adm/lastlog + AC_DEFINE(USE_PIPES) + ;; +*-ncr-sysv*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + LIBS="$LIBS -lc89" + AC_DEFINE(USE_PIPES) + ;; +*-sni-sysv*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + # /usr/ucblib MUST NOT be searched on ReliantUNIX + LDFLAGS="$LDFLAGS -L/usr/local/lib" + IPADDR_IN_DISPLAY=yes + AC_DEFINE(USE_PIPES) + AC_DEFINE(IP_TOS_IS_BROKEN) + # /usr/ucblib/libucb.a no longer needed on ReliantUNIX + # Attention: always take care to bind libsocket and libnsl before libc, + # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog + ;; +*-*-sysv4.2*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + AC_DEFINE(USE_PIPES) + ;; +*-*-sysv5*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + AC_DEFINE(USE_PIPES) + ;; +*-*-sysv*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + ;; +*-*-sco3.2v4*) + CPPFLAGS="$CPPFLAGS -Dftruncate=chsize -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + LIBS="$LIBS -los -lprot -lx -ltinfo -lm" + RANLIB=true + no_dev_ptmx=1 + AC_DEFINE(BROKEN_SYS_TERMIO_H) + AC_DEFINE(USE_PIPES) + AC_DEFINE(HAVE_SECUREWARE) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(BROKEN_SAVED_UIDS) + AC_CHECK_FUNCS(getluid setluid) + MANTYPE=man + do_sco3_extra_lib_check=yes + ;; +*-*-sco3.2v5*) + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + LIBS="$LIBS -lprot -lx -ltinfo -lm" + no_dev_ptmx=1 + AC_DEFINE(USE_PIPES) + AC_DEFINE(HAVE_SECUREWARE) + AC_DEFINE(DISABLE_SHADOW) + AC_DEFINE(BROKEN_FD_PASSING) + AC_CHECK_FUNCS(getluid setluid) + MANTYPE=man + ;; +*-*-unicos*) + no_libsocket=1 + no_libnsl=1 + AC_DEFINE(USE_PIPES) + AC_DEFINE(BROKEN_FD_PASSING) + LDFLAGS="$LDFLAGS -Wl,-Dmsglevel=334:fatal,-L/usr/local/lib" + LIBS="$LIBS -lgen -lrsc" + ;; +*-dec-osf*) + AC_MSG_CHECKING(for Digital Unix SIA) + no_osfsia="" + AC_ARG_WITH(osfsia, + [ --with-osfsia Enable Digital Unix SIA], + [ + if test "x$withval" = "xno" ; then + AC_MSG_RESULT(disabled) + no_osfsia=1 + fi + ], + ) + if test -z "$no_osfsia" ; then + if test -f /etc/sia/matrix.conf; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_OSF_SIA) + AC_DEFINE(DISABLE_LOGIN) + LIBS="$LIBS -lsecurity -ldb -lm -laud" + else + AC_MSG_RESULT(no) + fi + fi + ;; + +*-*-nto-qnx) + AC_DEFINE(USE_PIPES) + AC_DEFINE(NO_X11_UNIX_SOCKETS) + AC_DEFINE(MISSING_NFDBITS) + AC_DEFINE(MISSING_HOWMANY) + AC_DEFINE(MISSING_FD_MASK) + ;; +esac + +# Allow user to specify flags +AC_ARG_WITH(cflags, + [ --with-cflags Specify additional flags to pass to compiler], + [ + if test "x$withval" != "xno" ; then + CFLAGS="$CFLAGS $withval" + fi + ] +) +AC_ARG_WITH(cppflags, + [ --with-cppflags Specify additional flags to pass to preprocessor] , + [ + if test "x$withval" != "xno"; then + CPPFLAGS="$CPPFLAGS $withval" + fi + ] +) +AC_ARG_WITH(ldflags, + [ --with-ldflags Specify additional flags to pass to linker], + [ + if test "x$withval" != "xno" ; then + LDFLAGS="$LDFLAGS $withval" + fi + ] +) +AC_ARG_WITH(libs, + [ --with-libs Specify additional libraries to link with], + [ + if test "x$withval" != "xno" ; then + LIBS="$LIBS $withval" + fi + ] +) + +# Checks for header files. +AC_CHECK_HEADERS(bstring.h crypt.h endian.h floatingpoint.h \ + getopt.h glob.h lastlog.h limits.h login.h \ + login_cap.h maillock.h netdb.h netgroup.h \ + netinet/in_systm.h paths.h pty.h readpassphrase.h \ + rpc/types.h security/pam_appl.h shadow.h stddef.h stdint.h \ + strings.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h \ + sys/mman.h sys/select.h sys/stat.h \ + sys/stropts.h sys/sysmacros.h sys/time.h \ + sys/un.h time.h ttyent.h usersec.h \ + util.h utime.h utmp.h utmpx.h) + +# Checks for libraries. +AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match)) +AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) + +dnl SCO OS3 needs this for libwrap +if test "x$with_tcp_wrappers" != "xno" ; then + if test "x$do_sco3_extra_lib_check" = "xyes" ; then + AC_CHECK_LIB(rpc, innetgr, LIBS="-lrpc -lyp -lrpc $LIBS" , , -lyp -lrpc) + fi +fi + +AC_CHECK_FUNC(getspnam, , + AC_CHECK_LIB(gen, getspnam, LIBS="$LIBS -lgen")) + +AC_ARG_WITH(rpath, + [ --without-rpath Disable auto-added -R linker paths], + [ + if test "x$withval" = "xno" ; then + need_dash_r="" + fi + if test "x$withval" = "xyes" ; then + need_dash_r=1 + fi + ] +) + +dnl zlib is required +AC_ARG_WITH(zlib, + [ --with-zlib=PATH Use zlib in PATH], + [ + if test "x$withval" = "xno" ; then + AC_MSG_ERROR([*** zlib is required ***]) + fi + if test -d "$withval/lib"; then + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" + else + LDFLAGS="-L${withval}/lib ${LDFLAGS}" + fi + else + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" + else + LDFLAGS="-L${withval} ${LDFLAGS}" + fi + fi + if test -d "$withval/include"; then + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" + else + CPPFLAGS="-I${withval} ${CPPFLAGS}" + fi + ] +) + +AC_CHECK_LIB(z, deflate, ,AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***])) + +dnl UnixWare 2.x +AC_CHECK_FUNC(strcasecmp, + [], [ AC_CHECK_LIB(resolv, strcasecmp, LIBS="$LIBS -lresolv") ] +) +AC_CHECK_FUNC(utimes, + [], [ AC_CHECK_LIB(c89, utimes, LIBS="$LIBS -lc89") ] +) + +dnl Checks for libutil functions +AC_CHECK_HEADERS(libutil.h) +AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN)]) +AC_CHECK_FUNCS(logout updwtmp logwtmp) + +AC_FUNC_STRFTIME + +# Check for ALTDIRFUNC glob() extension +AC_MSG_CHECKING(for GLOB_ALTDIRFUNC support) +AC_EGREP_CPP(FOUNDIT, + [ + #include + #ifdef GLOB_ALTDIRFUNC + FOUNDIT + #endif + ], + [ + AC_DEFINE(GLOB_HAS_ALTDIRFUNC) + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + ] +) + +# Check for g.gl_matchc glob() extension +AC_MSG_CHECKING(for gl_matchc field in glob_t) +AC_EGREP_CPP(FOUNDIT, + [ + #include + int main(void){glob_t g; g.gl_matchc = 1;} + ], + [ + AC_DEFINE(GLOB_HAS_GL_MATCHC) + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + ] +) + +AC_MSG_CHECKING([whether struct dirent allocates space for d_name]) +AC_TRY_RUN( + [ +#include +#include +int main(void){struct dirent d;return(sizeof(d.d_name)<=sizeof(char));} + ], + [AC_MSG_RESULT(yes)], + [ + AC_MSG_RESULT(no) + AC_DEFINE(BROKEN_ONE_BYTE_DIRENT_D_NAME) + ] +) + +# Check whether user wants S/Key support +SKEY_MSG="no" +AC_ARG_WITH(skey, + [ --with-skey[[=PATH]] Enable S/Key support + (optionally in PATH)], + [ + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I${withval}/include" + LDFLAGS="$LDFLAGS -L${withval}/lib" + fi + + AC_DEFINE(SKEY) + LIBS="-lskey $LIBS" + SKEY_MSG="yes" + + AC_MSG_CHECKING([for s/key support]) + AC_TRY_RUN( + [ +#include +#include +int main() { char *ff = skey_keyinfo(""); ff=""; return 0; } + ], + [AC_MSG_RESULT(yes)], + [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([** Incomplete or missing s/key libraries.]) + ]) + fi + ] +) + +# Check whether user wants OPIE support +OPIE_MSG="no" +AC_ARG_WITH(opie, + [ --with-opie[[=PATH]] Enable OPIE support + (optionally in PATH)], + [ + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I${withval}/include" + LDFLAGS="$LDFLAGS -L${withval}/lib" + fi + + AC_DEFINE(SKEY) + AC_DEFINE(OPIE) + LIBS="-lopie $LIBS" + OPIE_MSG="yes" + + AC_MSG_CHECKING([for opie support]) + AC_TRY_RUN( + [ +#include +#include +#include +int main() { char *ff = opie_keyinfo(""); ff=""; return 0; } + ], + [AC_MSG_RESULT(yes)], + [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([** Incomplete or missing opie libraries.]) + ]) + fi + ] +) + +# Check whether user wants TCP wrappers support +TCPW_MSG="no" +AC_ARG_WITH(tcp-wrappers, + [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support + (optionally in PATH)], + [ + if test "x$withval" != "xno" ; then + saved_LIBS="$LIBS" + saved_LDFLAGS="$LDFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + if test -n "${withval}" -a "${withval}" != "yes"; then + if test -d "${withval}/lib"; then + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" + else + LDFLAGS="-L${withval}/lib ${LDFLAGS}" + fi + else + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" + else + LDFLAGS="-L${withval} ${LDFLAGS}" + fi + fi + if test -d "${withval}/include"; then + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" + else + CPPFLAGS="-I${withval} ${CPPFLAGS}" + fi + fi + LIBWRAP="-lwrap" + LIBS="$LIBWRAP $LIBS" + AC_MSG_CHECKING(for libwrap) + AC_TRY_LINK( + [ +#include + int deny_severity = 0, allow_severity = 0; + ], + [hosts_access(0);], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(LIBWRAP) + AC_SUBST(LIBWRAP) + TCPW_MSG="yes" + ], + [ + AC_MSG_ERROR([*** libwrap missing]) + ] + ) + LIBS="$saved_LIBS" + fi + ] +) + +dnl Checks for library functions. +AC_CHECK_FUNCS(arc4random b64_ntop bcopy bindresvport_sa \ + clock fchmod fchown freeaddrinfo futimes gai_strerror \ + getaddrinfo getcwd getgrouplist getnameinfo getopt \ + getrlimit getrusage getttyent glob inet_aton inet_ntoa \ + inet_ntop innetgr login_getcapbool md5_crypt memmove \ + mkdtemp mmap ngetaddrinfo openpty ogetaddrinfo readpassphrase \ + realpath recvmsg rresvport_af sendmsg setdtablesize setegid \ + setenv seteuid setgroups setlogin setproctitle setresgid setreuid \ + setrlimit setsid setpcred setvbuf sigaction sigvec snprintf \ + socketpair strerror strlcat strlcpy strmode strsep sysconf tcgetpgrp \ + truncate utimes vhangup vsnprintf waitpid __b64_ntop _getpty) + +if test $ac_cv_func_mmap = yes ; then +AC_MSG_CHECKING([for mmap anon shared]) +AC_TRY_RUN( + [ +#include +#include +#include +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +#define MAP_ANON MAP_ANONYMOUS +#endif +main() { char *p; +p = (char *) mmap(NULL, 10, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, -1, 0); +if (p == (char *)-1) + exit(1); +exit(0); +} + ], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MMAP_ANON_SHARED) + ], + [ AC_MSG_RESULT(no) ] +) +fi + +dnl IRIX and Solaris 2.5.1 have dirname() in libgen +AC_CHECK_FUNCS(dirname, [AC_CHECK_HEADERS(libgen.h)] ,[ + AC_CHECK_LIB(gen, dirname,[ + AC_CACHE_CHECK([for broken dirname], + ac_cv_have_broken_dirname, [ + save_LIBS="$LIBS" + LIBS="$LIBS -lgen" + AC_TRY_RUN( + [ +#include +#include + +int main(int argc, char **argv) { + char *s, buf[32]; + + strncpy(buf,"/etc", 32); + s = dirname(buf); + if (!s || strncmp(s, "/", 32) != 0) { + exit(1); + } else { + exit(0); + } +} + ], + [ ac_cv_have_broken_dirname="no" ], + [ ac_cv_have_broken_dirname="yes" ] + ) + LIBS="$save_LIBS" + ]) + if test "x$ac_cv_have_broken_dirname" = "xno" ; then + LIBS="$LIBS -lgen" + AC_DEFINE(HAVE_DIRNAME) + AC_CHECK_HEADERS(libgen.h) + fi + ]) +]) + +dnl Checks for time functions +AC_CHECK_FUNCS(gettimeofday time) +dnl Checks for utmp functions +AC_CHECK_FUNCS(endutent getutent getutid getutline pututline setutent) +AC_CHECK_FUNCS(utmpname) +dnl Checks for utmpx functions +AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline ) +AC_CHECK_FUNCS(setutxent utmpxname) + +AC_CHECK_FUNC(daemon, + [AC_DEFINE(HAVE_DAEMON)], + [AC_CHECK_LIB(bsd, daemon, [LIBS="$LIBS -lbsd"; AC_DEFINE(HAVE_DAEMON)])] +) + +AC_CHECK_FUNC(getpagesize, + [AC_DEFINE(HAVE_GETPAGESIZE)], + [AC_CHECK_LIB(ucb, getpagesize, [LIBS="$LIBS -lucb"; AC_DEFINE(HAVE_GETPAGESIZE)])] +) + +# Check for broken snprintf +if test "x$ac_cv_func_snprintf" = "xyes" ; then + AC_MSG_CHECKING([whether snprintf correctly terminates long strings]) + AC_TRY_RUN( + [ +#include +int main(void){char b[5];snprintf(b,5,"123456789");return(b[4]!='\0');} + ], + [AC_MSG_RESULT(yes)], + [ + AC_MSG_RESULT(no) + AC_DEFINE(BROKEN_SNPRINTF) + AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor]) + ] + ) +fi + +AC_FUNC_GETPGRP + +# Check for PAM libs +PAM_MSG="no" +AC_ARG_WITH(pam, + [ --with-pam Enable PAM support ], + [ + if test "x$withval" != "xno" ; then + if test "x$ac_cv_header_security_pam_appl_h" != "xyes" ; then + AC_MSG_ERROR([PAM headers not found]) + fi + + AC_CHECK_LIB(dl, dlopen, , ) + AC_CHECK_LIB(pam, pam_set_item, , AC_MSG_ERROR([*** libpam missing])) + AC_CHECK_FUNCS(pam_getenvlist) + + disable_shadow=yes + PAM_MSG="yes" + + AC_DEFINE(USE_PAM) + if test $ac_cv_lib_dl_dlopen = yes; then + LIBPAM="-lpam -ldl" + else + LIBPAM="-lpam" + fi + AC_SUBST(LIBPAM) + fi + ] +) + +# Check for older PAM +if test "x$PAM_MSG" = "xyes" ; then + # Check PAM strerror arguments (old PAM) + AC_MSG_CHECKING([whether pam_strerror takes only one argument]) + AC_TRY_COMPILE( + [ +#include +#include + ], + [(void)pam_strerror((pam_handle_t *)NULL, -1);], + [AC_MSG_RESULT(no)], + [ + AC_DEFINE(HAVE_OLD_PAM) + AC_MSG_RESULT(yes) + PAM_MSG="yes (old library)" + ] + ) +fi + +# Search for OpenSSL +saved_CPPFLAGS="$CPPFLAGS" +saved_LDFLAGS="$LDFLAGS" +AC_ARG_WITH(ssl-dir, + [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], + [ + if test "x$withval" != "xno" ; then + if test -d "$withval/lib"; then + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" + else + LDFLAGS="-L${withval}/lib ${LDFLAGS}" + fi + else + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" + else + LDFLAGS="-L${withval} ${LDFLAGS}" + fi + fi + if test -d "$withval/include"; then + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" + else + CPPFLAGS="-I${withval} ${CPPFLAGS}" + fi + fi + ] +) +LIBS="$LIBS -lcrypto" +AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL), + [ + dnl Check default openssl install dir + if test -n "${need_dash_r}"; then + LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}" + else + LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}" + fi + CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}" + AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL), + [ + AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***]) + ] + ) + ] +) + + +# Sanity check OpenSSL headers +AC_MSG_CHECKING([whether OpenSSL's headers match the library]) +AC_TRY_RUN( + [ +#include +#include +int main(void) { return(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); } + ], + [ + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + AC_MSG_ERROR(Your OpenSSL headers do not match your library) + ] +) + +# Some Linux systems (Slackware) need crypt() from libcrypt, *not* the +# version in OpenSSL. Skip this for PAM +if test "x$PAM_MSG" = "xno" -a "x$check_for_libcrypt_later" = "x1"; then + AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt") +fi + + +### Configure cryptographic random number support + +# Check wheter OpenSSL seeds itself +AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) +AC_TRY_RUN( + [ +#include +#include +int main(void) { return(RAND_status() == 1 ? 0 : 1); } + ], + [ + OPENSSL_SEEDS_ITSELF=yes + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + # Default to use of the rand helper if OpenSSL doesn't + # seed itself + USE_RAND_HELPER=yes + ] +) + + +# Do we want to force the use of the rand helper? +AC_ARG_WITH(rand-helper, + [ --with-rand-helper Use subprocess to gather strong randomness ], + [ + if test "x$withval" = "xno" ; then + # Force use of OpenSSL's internal RNG, even if + # the previous test showed it to be unseeded. + if test -z "$OPENSSL_SEEDS_ITSELF" ; then + AC_MSG_WARN([*** Forcing use of OpenSSL's non-self-seeding PRNG]) + OPENSSL_SEEDS_ITSELF=yes + USE_RAND_HELPER="" + fi + else + USE_RAND_HELPER=yes + fi + ], +) + +# Which randomness source do we use? +if test ! -z "$OPENSSL_SEEDS_ITSELF" -a -z "$USE_RAND_HELPER" ; then + # OpenSSL only + AC_DEFINE(OPENSSL_PRNG_ONLY) + RAND_MSG="OpenSSL internal ONLY" + INSTALL_SSH_RAND_HELPER="" +elif test ! -z "$USE_RAND_HELPER" ; then + # install rand helper + RAND_MSG="ssh-rand-helper" + INSTALL_SSH_RAND_HELPER="yes" +fi +AC_SUBST(INSTALL_SSH_RAND_HELPER) + +### Configuration of ssh-rand-helper + +# PRNGD TCP socket +AC_ARG_WITH(prngd-port, + [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT], + [ + case "$withval" in + no) + withval="" + ;; + [[0-9]]*) + ;; + *) + AC_MSG_ERROR(You must specify a numeric port number for --with-prngd-port) + ;; + esac + if test ! -z "$withval" ; then + PRNGD_PORT="$withval" + AC_DEFINE_UNQUOTED(PRNGD_PORT, $PRNGD_PORT) + fi + ] +) + +# PRNGD Unix domain socket +AC_ARG_WITH(prngd-socket, + [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], + [ + case "$withval" in + yes) + withval="/var/run/egd-pool" + ;; + no) + withval="" + ;; + /*) + ;; + *) + AC_MSG_ERROR(You must specify an absolute path to the entropy socket) + ;; + esac + + if test ! -z "$withval" ; then + if test ! -z "$PRNGD_PORT" ; then + AC_MSG_ERROR(You may not specify both a PRNGD/EGD port and socket) + fi + if test ! -r "$withval" ; then + AC_MSG_WARN(Entropy socket is not readable) + fi + PRNGD_SOCKET="$withval" + AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") + fi + ], + [ + # Check for existing socket only if we don't have a random device already + if test "$USE_RAND_HELPER" = yes ; then + AC_MSG_CHECKING(for PRNGD/EGD socket) + # Insert other locations here + for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do + if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then + PRNGD_SOCKET="$sock" + AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") + break; + fi + done + if test ! -z "$PRNGD_SOCKET" ; then + AC_MSG_RESULT($PRNGD_SOCKET) + else + AC_MSG_RESULT(not found) + fi + fi + ] +) + +# Change default command timeout for hashing entropy source +entropy_timeout=200 +AC_ARG_WITH(entropy-timeout, + [ --with-entropy-timeout Specify entropy gathering command timeout (msec)], + [ + if test "x$withval" != "xno" ; then + entropy_timeout=$withval + fi + ] +) +AC_DEFINE_UNQUOTED(ENTROPY_TIMEOUT_MSEC, $entropy_timeout) + +SSH_PRIVSEP_USER=sshd +AC_ARG_WITH(privsep-user, + [ --with-privsep-user=user Specify non-privileged user for privilege separation], + [ + if test -n "$withval"; then + SSH_PRIVSEP_USER=$withval + fi + ] +) +AC_DEFINE_UNQUOTED(SSH_PRIVSEP_USER, "$SSH_PRIVSEP_USER") +AC_SUBST(SSH_PRIVSEP_USER) + +# We do this little dance with the search path to insure +# that programs that we select for use by installed programs +# (which may be run by the super-user) come from trusted +# locations before they come from the user's private area. +# This should help avoid accidentally configuring some +# random version of a program in someone's personal bin. + +OPATH=$PATH +PATH=/bin:/usr/bin +test -h /bin 2> /dev/null && PATH=/usr/bin +test -d /sbin && PATH=$PATH:/sbin +test -d /usr/sbin && PATH=$PATH:/usr/sbin +PATH=$PATH:/etc:$OPATH + +# These programs are used by the command hashing source to gather entropy +OSSH_PATH_ENTROPY_PROG(PROG_LS, ls) +OSSH_PATH_ENTROPY_PROG(PROG_NETSTAT, netstat) +OSSH_PATH_ENTROPY_PROG(PROG_ARP, arp) +OSSH_PATH_ENTROPY_PROG(PROG_IFCONFIG, ifconfig) +OSSH_PATH_ENTROPY_PROG(PROG_JSTAT, jstat) +OSSH_PATH_ENTROPY_PROG(PROG_PS, ps) +OSSH_PATH_ENTROPY_PROG(PROG_SAR, sar) +OSSH_PATH_ENTROPY_PROG(PROG_W, w) +OSSH_PATH_ENTROPY_PROG(PROG_WHO, who) +OSSH_PATH_ENTROPY_PROG(PROG_LAST, last) +OSSH_PATH_ENTROPY_PROG(PROG_LASTLOG, lastlog) +OSSH_PATH_ENTROPY_PROG(PROG_DF, df) +OSSH_PATH_ENTROPY_PROG(PROG_VMSTAT, vmstat) +OSSH_PATH_ENTROPY_PROG(PROG_UPTIME, uptime) +OSSH_PATH_ENTROPY_PROG(PROG_IPCS, ipcs) +OSSH_PATH_ENTROPY_PROG(PROG_TAIL, tail) +# restore PATH +PATH=$OPATH + +# Where does ssh-rand-helper get its randomness from? +INSTALL_SSH_PRNG_CMDS="" +if test ! -z "$INSTALL_SSH_RAND_HELPER" ; then + if test ! -z "$PRNGD_PORT" ; then + RAND_HELPER_MSG="TCP localhost:$PRNGD_PORT" + elif test ! -z "$PRNGD_SOCKET" ; then + RAND_HELPER_MSG="Unix domain socket \"$PRNGD_SOCKET\"" + else + RAND_HELPER_MSG="Command hashing (timeout $entropy_timeout)" + RAND_HELPER_CMDHASH=yes + INSTALL_SSH_PRNG_CMDS="yes" + fi +fi +AC_SUBST(INSTALL_SSH_PRNG_CMDS) + + +# Cheap hack to ensure NEWS-OS libraries are arranged right. +if test ! -z "$SONY" ; then + LIBS="$LIBS -liberty"; +fi + +# Checks for data types +AC_CHECK_SIZEOF(char, 1) +AC_CHECK_SIZEOF(short int, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long int, 4) +AC_CHECK_SIZEOF(long long int, 8) + +# Sanity check long long for some platforms (AIX) +if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then + ac_cv_sizeof_long_long_int=0 +fi + +# More checks for data types +AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [ + AC_TRY_COMPILE( + [ #include ], + [ u_int a; a = 1;], + [ ac_cv_have_u_int="yes" ], + [ ac_cv_have_u_int="no" ] + ) +]) +if test "x$ac_cv_have_u_int" = "xyes" ; then + AC_DEFINE(HAVE_U_INT) + have_u_int=1 +fi + +AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [ + AC_TRY_COMPILE( + [ #include ], + [ int8_t a; int16_t b; int32_t c; a = b = c = 1;], + [ ac_cv_have_intxx_t="yes" ], + [ ac_cv_have_intxx_t="no" ] + ) +]) +if test "x$ac_cv_have_intxx_t" = "xyes" ; then + AC_DEFINE(HAVE_INTXX_T) + have_intxx_t=1 +fi + +if (test -z "$have_intxx_t" && \ + test "x$ac_cv_header_stdint_h" = "xyes") +then + AC_MSG_CHECKING([for intXX_t types in stdint.h]) + AC_TRY_COMPILE( + [ #include ], + [ int8_t a; int16_t b; int32_t c; a = b = c = 1;], + [ + AC_DEFINE(HAVE_INTXX_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + +AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [ + AC_TRY_COMPILE( + [ #include ], + [ int64_t a; a = 1;], + [ ac_cv_have_int64_t="yes" ], + [ ac_cv_have_int64_t="no" ] + ) +]) +if test "x$ac_cv_have_int64_t" = "xyes" ; then + AC_DEFINE(HAVE_INT64_T) + have_int64_t=1 +fi + +if test -z "$have_int64_t" ; then + AC_MSG_CHECKING([for int64_t type in sys/socket.h]) + AC_TRY_COMPILE( + [ #include ], + [ int64_t a; a = 1], + [ + AC_DEFINE(HAVE_INT64_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + +if test -z "$have_int64_t" ; then + AC_MSG_CHECKING([for int64_t type in sys/bitypes.h]) + AC_TRY_COMPILE( + [ #include ], + [ int64_t a; a = 1], + [ + AC_DEFINE(HAVE_INT64_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + +AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [ + AC_TRY_COMPILE( + [ #include ], + [ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;], + [ ac_cv_have_u_intxx_t="yes" ], + [ ac_cv_have_u_intxx_t="no" ] + ) +]) +if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then + AC_DEFINE(HAVE_U_INTXX_T) + have_u_intxx_t=1 +fi + +if test -z "$have_u_intxx_t" ; then + AC_MSG_CHECKING([for u_intXX_t types in sys/socket.h]) + AC_TRY_COMPILE( + [ #include ], + [ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;], + [ + AC_DEFINE(HAVE_U_INTXX_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + +AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [ + AC_TRY_COMPILE( + [ #include ], + [ u_int64_t a; a = 1;], + [ ac_cv_have_u_int64_t="yes" ], + [ ac_cv_have_u_int64_t="no" ] + ) +]) +if test "x$ac_cv_have_u_int64_t" = "xyes" ; then + AC_DEFINE(HAVE_U_INT64_T) + have_u_int64_t=1 +fi + +if test -z "$have_u_int64_t" ; then + AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h]) + AC_TRY_COMPILE( + [ #include ], + [ u_int64_t a; a = 1], + [ + AC_DEFINE(HAVE_U_INT64_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + +if test -z "$have_u_intxx_t" ; then + AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [ + AC_TRY_COMPILE( + [ +#include + ], + [ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ], + [ ac_cv_have_uintxx_t="yes" ], + [ ac_cv_have_uintxx_t="no" ] + ) + ]) + if test "x$ac_cv_have_uintxx_t" = "xyes" ; then + AC_DEFINE(HAVE_UINTXX_T) + fi +fi + +if test -z "$have_uintxx_t" ; then + AC_MSG_CHECKING([for uintXX_t types in stdint.h]) + AC_TRY_COMPILE( + [ #include ], + [ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;], + [ + AC_DEFINE(HAVE_UINTXX_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + +if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ + test "x$ac_cv_header_sys_bitypes_h" = "xyes") +then + AC_MSG_CHECKING([for intXX_t and u_intXX_t types in sys/bitypes.h]) + AC_TRY_COMPILE( + [ +#include + ], + [ + int8_t a; int16_t b; int32_t c; + u_int8_t e; u_int16_t f; u_int32_t g; + a = b = c = e = f = g = 1; + ], + [ + AC_DEFINE(HAVE_U_INTXX_T) + AC_DEFINE(HAVE_INTXX_T) + AC_MSG_RESULT(yes) + ], + [AC_MSG_RESULT(no)] + ) +fi + + +AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [ + AC_TRY_COMPILE( + [ +#include + ], + [ u_char foo; foo = 125; ], + [ ac_cv_have_u_char="yes" ], + [ ac_cv_have_u_char="no" ] + ) +]) +if test "x$ac_cv_have_u_char" = "xyes" ; then + AC_DEFINE(HAVE_U_CHAR) +fi + +TYPE_SOCKLEN_T + +AC_CHECK_TYPES(sig_atomic_t,,,[#include ]) + +AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [ + AC_TRY_COMPILE( + [ +#include + ], + [ size_t foo; foo = 1235; ], + [ ac_cv_have_size_t="yes" ], + [ ac_cv_have_size_t="no" ] + ) +]) +if test "x$ac_cv_have_size_t" = "xyes" ; then + AC_DEFINE(HAVE_SIZE_T) +fi + +AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [ + AC_TRY_COMPILE( + [ +#include + ], + [ ssize_t foo; foo = 1235; ], + [ ac_cv_have_ssize_t="yes" ], + [ ac_cv_have_ssize_t="no" ] + ) +]) +if test "x$ac_cv_have_ssize_t" = "xyes" ; then + AC_DEFINE(HAVE_SSIZE_T) +fi + +AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [ + AC_TRY_COMPILE( + [ +#include + ], + [ clock_t foo; foo = 1235; ], + [ ac_cv_have_clock_t="yes" ], + [ ac_cv_have_clock_t="no" ] + ) +]) +if test "x$ac_cv_have_clock_t" = "xyes" ; then + AC_DEFINE(HAVE_CLOCK_T) +fi + +AC_CACHE_CHECK([for sa_family_t], ac_cv_have_sa_family_t, [ + AC_TRY_COMPILE( + [ +#include +#include + ], + [ sa_family_t foo; foo = 1235; ], + [ ac_cv_have_sa_family_t="yes" ], + [ AC_TRY_COMPILE( + [ +#include +#include +#include + ], + [ sa_family_t foo; foo = 1235; ], + [ ac_cv_have_sa_family_t="yes" ], + + [ ac_cv_have_sa_family_t="no" ] + )] + ) +]) +if test "x$ac_cv_have_sa_family_t" = "xyes" ; then + AC_DEFINE(HAVE_SA_FAMILY_T) +fi + +AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [ + AC_TRY_COMPILE( + [ +#include + ], + [ pid_t foo; foo = 1235; ], + [ ac_cv_have_pid_t="yes" ], + [ ac_cv_have_pid_t="no" ] + ) +]) +if test "x$ac_cv_have_pid_t" = "xyes" ; then + AC_DEFINE(HAVE_PID_T) +fi + +AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [ + AC_TRY_COMPILE( + [ +#include + ], + [ mode_t foo; foo = 1235; ], + [ ac_cv_have_mode_t="yes" ], + [ ac_cv_have_mode_t="no" ] + ) +]) +if test "x$ac_cv_have_mode_t" = "xyes" ; then + AC_DEFINE(HAVE_MODE_T) +fi + + +AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [ + AC_TRY_COMPILE( + [ +#include +#include + ], + [ struct sockaddr_storage s; ], + [ ac_cv_have_struct_sockaddr_storage="yes" ], + [ ac_cv_have_struct_sockaddr_storage="no" ] + ) +]) +if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE) +fi + +AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [ + AC_TRY_COMPILE( + [ +#include +#include + ], + [ struct sockaddr_in6 s; s.sin6_family = 0; ], + [ ac_cv_have_struct_sockaddr_in6="yes" ], + [ ac_cv_have_struct_sockaddr_in6="no" ] + ) +]) +if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6) +fi + +AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [ + AC_TRY_COMPILE( + [ +#include +#include + ], + [ struct in6_addr s; s.s6_addr[0] = 0; ], + [ ac_cv_have_struct_in6_addr="yes" ], + [ ac_cv_have_struct_in6_addr="no" ] + ) +]) +if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_IN6_ADDR) +fi + +AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [ + AC_TRY_COMPILE( + [ +#include +#include +#include + ], + [ struct addrinfo s; s.ai_flags = AI_PASSIVE; ], + [ ac_cv_have_struct_addrinfo="yes" ], + [ ac_cv_have_struct_addrinfo="no" ] + ) +]) +if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_ADDRINFO) +fi + +AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [ + AC_TRY_COMPILE( + [ #include ], + [ struct timeval tv; tv.tv_sec = 1;], + [ ac_cv_have_struct_timeval="yes" ], + [ ac_cv_have_struct_timeval="no" ] + ) +]) +if test "x$ac_cv_have_struct_timeval" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_TIMEVAL) + have_struct_timeval=1 +fi + +# If we don't have int64_t then we can't compile sftp-server. So don't +# even attempt to do it. +if test "x$ac_cv_have_int64_t" = "xno" -a \ + "x$ac_cv_sizeof_long_int" != "x8" -a \ + "x$ac_cv_sizeof_long_long_int" = "x0" ; then + NO_SFTP='#' +else +dnl test snprintf (broken on SCO w/gcc) + AC_TRY_RUN( + [ +#include +#include +#ifdef HAVE_SNPRINTF +main() +{ + char buf[50]; + char expected_out[50]; + int mazsize = 50 ; +#if (SIZEOF_LONG_INT == 8) + long int num = 0x7fffffffffffffff; +#else + long long num = 0x7fffffffffffffffll; +#endif + strcpy(expected_out, "9223372036854775807"); + snprintf(buf, mazsize, "%lld", num); + if(strcmp(buf, expected_out) != 0) + exit(1); + exit(0); +} +#else +main() { exit(0); } +#endif + ], [ true ], [ AC_DEFINE(BROKEN_SNPRINTF) ] + ) +fi +AC_SUBST(NO_SFTP) + +dnl Checks for structure members +OSSH_CHECK_HEADER_FOR_FIELD(ut_host, utmp.h, HAVE_HOST_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_host, utmpx.h, HAVE_HOST_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(syslen, utmpx.h, HAVE_SYSLEN_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(ut_pid, utmp.h, HAVE_PID_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_type, utmp.h, HAVE_TYPE_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_type, utmpx.h, HAVE_TYPE_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmp.h, HAVE_TV_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_id, utmp.h, HAVE_ID_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_id, utmpx.h, HAVE_ID_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(ut_addr, utmp.h, HAVE_ADDR_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_addr, utmpx.h, HAVE_ADDR_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(ut_addr_v6, utmp.h, HAVE_ADDR_V6_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_addr_v6, utmpx.h, HAVE_ADDR_V6_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(ut_exit, utmp.h, HAVE_EXIT_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmp.h, HAVE_TIME_IN_UTMP) +OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX) +OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX) + +AC_CHECK_MEMBERS([struct stat.st_blksize]) + +AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], + ac_cv_have_ss_family_in_struct_ss, [ + AC_TRY_COMPILE( + [ +#include +#include + ], + [ struct sockaddr_storage s; s.ss_family = 1; ], + [ ac_cv_have_ss_family_in_struct_ss="yes" ], + [ ac_cv_have_ss_family_in_struct_ss="no" ], + ) +]) +if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then + AC_DEFINE(HAVE_SS_FAMILY_IN_SS) +fi + +AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage], + ac_cv_have___ss_family_in_struct_ss, [ + AC_TRY_COMPILE( + [ +#include +#include + ], + [ struct sockaddr_storage s; s.__ss_family = 1; ], + [ ac_cv_have___ss_family_in_struct_ss="yes" ], + [ ac_cv_have___ss_family_in_struct_ss="no" ] + ) +]) +if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then + AC_DEFINE(HAVE___SS_FAMILY_IN_SS) +fi + +AC_CACHE_CHECK([for pw_class field in struct passwd], + ac_cv_have_pw_class_in_struct_passwd, [ + AC_TRY_COMPILE( + [ +#include + ], + [ struct passwd p; p.pw_class = 0; ], + [ ac_cv_have_pw_class_in_struct_passwd="yes" ], + [ ac_cv_have_pw_class_in_struct_passwd="no" ] + ) +]) +if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then + AC_DEFINE(HAVE_PW_CLASS_IN_PASSWD) +fi + +AC_CACHE_CHECK([for pw_expire field in struct passwd], + ac_cv_have_pw_expire_in_struct_passwd, [ + AC_TRY_COMPILE( + [ +#include + ], + [ struct passwd p; p.pw_expire = 0; ], + [ ac_cv_have_pw_expire_in_struct_passwd="yes" ], + [ ac_cv_have_pw_expire_in_struct_passwd="no" ] + ) +]) +if test "x$ac_cv_have_pw_expire_in_struct_passwd" = "xyes" ; then + AC_DEFINE(HAVE_PW_EXPIRE_IN_PASSWD) +fi + +AC_CACHE_CHECK([for pw_change field in struct passwd], + ac_cv_have_pw_change_in_struct_passwd, [ + AC_TRY_COMPILE( + [ +#include + ], + [ struct passwd p; p.pw_change = 0; ], + [ ac_cv_have_pw_change_in_struct_passwd="yes" ], + [ ac_cv_have_pw_change_in_struct_passwd="no" ] + ) +]) +if test "x$ac_cv_have_pw_change_in_struct_passwd" = "xyes" ; then + AC_DEFINE(HAVE_PW_CHANGE_IN_PASSWD) +fi + +dnl make sure we're using the real structure members and not defines +AC_CACHE_CHECK([for msg_accrights field in struct msghdr], + ac_cv_have_accrights_in_msghdr, [ + AC_TRY_RUN( + [ +#include +#include +#include +int main() { +#ifdef msg_accrights +exit(1); +#endif +struct msghdr m; +m.msg_accrights = 0; +exit(0); +} + ], + [ ac_cv_have_accrights_in_msghdr="yes" ], + [ ac_cv_have_accrights_in_msghdr="no" ] + ) +]) +if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then + AC_DEFINE(HAVE_ACCRIGHTS_IN_MSGHDR) +fi + +AC_CACHE_CHECK([for msg_control field in struct msghdr], + ac_cv_have_control_in_msghdr, [ + AC_TRY_RUN( + [ +#include +#include +#include +int main() { +#ifdef msg_control +exit(1); +#endif +struct msghdr m; +m.msg_control = 0; +exit(0); +} + ], + [ ac_cv_have_control_in_msghdr="yes" ], + [ ac_cv_have_control_in_msghdr="no" ] + ) +]) +if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then + AC_DEFINE(HAVE_CONTROL_IN_MSGHDR) +fi + +AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ + AC_TRY_LINK([], + [ extern char *__progname; printf("%s", __progname); ], + [ ac_cv_libc_defines___progname="yes" ], + [ ac_cv_libc_defines___progname="no" ] + ) +]) +if test "x$ac_cv_libc_defines___progname" = "xyes" ; then + AC_DEFINE(HAVE___PROGNAME) +fi + +AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNCTION__, [ + AC_TRY_LINK([ +#include +], + [ printf("%s", __FUNCTION__); ], + [ ac_cv_cc_implements___FUNCTION__="yes" ], + [ ac_cv_cc_implements___FUNCTION__="no" ] + ) +]) +if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then + AC_DEFINE(HAVE___FUNCTION__) +fi + +AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__, [ + AC_TRY_LINK([ +#include +], + [ printf("%s", __func__); ], + [ ac_cv_cc_implements___func__="yes" ], + [ ac_cv_cc_implements___func__="no" ] + ) +]) +if test "x$ac_cv_cc_implements___func__" = "xyes" ; then + AC_DEFINE(HAVE___func__) +fi + +AC_CACHE_CHECK([whether getopt has optreset support], + ac_cv_have_getopt_optreset, [ + AC_TRY_LINK( + [ +#if HAVE_GETOPT_H +#include +#elif HAVE_UNISTD_H +#include +#endif + ], + [ extern int optreset; optreset = 0; ], + [ ac_cv_have_getopt_optreset="yes" ], + [ ac_cv_have_getopt_optreset="no" ] + ) +]) +if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then + AC_DEFINE(HAVE_GETOPT_OPTRESET) +fi + +AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ + AC_TRY_LINK([], + [ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);], + [ ac_cv_libc_defines_sys_errlist="yes" ], + [ ac_cv_libc_defines_sys_errlist="no" ] + ) +]) +if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then + AC_DEFINE(HAVE_SYS_ERRLIST) +fi + + +AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ + AC_TRY_LINK([], + [ extern int sys_nerr; printf("%i", sys_nerr);], + [ ac_cv_libc_defines_sys_nerr="yes" ], + [ ac_cv_libc_defines_sys_nerr="no" ] + ) +]) +if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then + AC_DEFINE(HAVE_SYS_NERR) +fi + +SCARD_MSG="no" + +# Check whether user wants sectok support +AC_ARG_WITH(sectok, + [ --with-sectok Enable smartcard support using libsectok], + [ + if test "x$withval" != "xno" ; then + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I${withval}" + LDFLAGS="$LDFLAGS -L${withval}" + if test ! -z "$need_dash_r" ; then + LDFLAGS="$LDFLAGS -R${withval}" + fi + if test ! -z "$blibpath" ; then + blibpath="$blibpath:${withval}" + fi + fi + AC_CHECK_HEADERS(sectok.h) + if test "$ac_cv_header_sectok_h" != yes; then + AC_MSG_ERROR(Can't find sectok.h) + fi + AC_CHECK_LIB(sectok, sectok_open) + if test "$ac_cv_lib_sectok_sectok_open" != yes; then + AC_MSG_ERROR(Can't find libsectok) + fi + AC_DEFINE(SMARTCARD) + AC_DEFINE(USE_SECTOK) + SCARD_MSG="yes, using sectok" + fi + ] +) + +# Check whether user wants OpenSC support +AC_ARG_WITH(opensc, + AC_HELP_STRING([--with-opensc=PFX], + [Enable smartcard support using OpenSC]), + opensc_config_prefix="$withval", opensc_config_prefix="") +if test x$opensc_config_prefix != x ; then + OPENSC_CONFIG=$opensc_config_prefix/bin/opensc-config + AC_PATH_PROG(OPENSC_CONFIG, opensc-config, no) + if test "$OPENSC_CONFIG" != "no"; then + LIBOPENSC_CFLAGS=`$OPENSC_CONFIG --cflags` + LIBOPENSC_LIBS=`$OPENSC_CONFIG --libs` + CPPFLAGS="$CPPFLAGS $LIBOPENSC_CFLAGS" + LDFLAGS="$LDFLAGS $LIBOPENSC_LIBS" + AC_DEFINE(SMARTCARD) + AC_DEFINE(USE_OPENSC) + SCARD_MSG="yes, using OpenSC" + fi +fi + +# Check whether user wants Kerberos 5 support +KRB5_MSG="no" +AC_ARG_WITH(kerberos5, + [ --with-kerberos5=PATH Enable Kerberos 5 support], + [ + if test "x$withval" != "xno" ; then + if test "x$withval" = "xyes" ; then + KRB5ROOT="/usr/local" + else + KRB5ROOT=${withval} + fi + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" + LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" + AC_DEFINE(KRB5) + KRB5_MSG="yes" + AC_MSG_CHECKING(whether we are using Heimdal) + AC_TRY_COMPILE([ #include ], + [ char *tmp = heimdal_version; ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(HEIMDAL) + K5LIBS="-lkrb5 -ldes -lcom_err -lasn1 -lroken" + ], + [ AC_MSG_RESULT(no) + K5LIBS="-lkrb5 -lk5crypto -lcom_err" + ] + ) + if test ! -z "$need_dash_r" ; then + LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib" + fi + if test ! -z "$blibpath" ; then + blibpath="$blibpath:${KRB5ROOT}/lib" + fi + AC_CHECK_LIB(resolv, dn_expand, , ) + + KRB5=yes + fi + ] +) +# Check whether user wants Kerberos 4 support +KRB4_MSG="no" +AC_ARG_WITH(kerberos4, + [ --with-kerberos4=PATH Enable Kerberos 4 support], + [ + if test "x$withval" != "xno" ; then + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I${withval}/include" + LDFLAGS="$LDFLAGS -L${withval}/lib" + if test ! -z "$need_dash_r" ; then + LDFLAGS="$LDFLAGS -R${withval}/lib" + fi + if test ! -z "$blibpath" ; then + blibpath="$blibpath:${withval}/lib" + fi + else + if test -d /usr/include/kerberosIV ; then + CPPFLAGS="$CPPFLAGS -I/usr/include/kerberosIV" + fi + fi + + AC_CHECK_HEADERS(krb.h) + if test "$ac_cv_header_krb_h" != yes; then + AC_MSG_WARN([Cannot find krb.h, build may fail]) + fi + AC_CHECK_LIB(krb, main) + if test "$ac_cv_lib_krb_main" != yes; then + AC_CHECK_LIB(krb4, main) + if test "$ac_cv_lib_krb4_main" != yes; then + AC_MSG_WARN([Cannot find libkrb nor libkrb4, build may fail]) + else + KLIBS="-lkrb4" + fi + else + KLIBS="-lkrb" + fi + AC_CHECK_LIB(des, des_cbc_encrypt) + if test "$ac_cv_lib_des_des_cbc_encrypt" != yes; then + AC_CHECK_LIB(des425, des_cbc_encrypt) + if test "$ac_cv_lib_des425_des_cbc_encrypt" != yes; then + AC_MSG_WARN([Cannot find libdes nor libdes425, build may fail]) + else + KLIBS="-ldes425" + fi + else + KLIBS="-ldes" + fi + AC_CHECK_LIB(resolv, dn_expand, , ) + KRB4=yes + KRB4_MSG="yes" + AC_DEFINE(KRB4) + fi + ] +) + +# Check whether user wants AFS support +AFS_MSG="no" +AC_ARG_WITH(afs, + [ --with-afs=PATH Enable AFS support], + [ + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I${withval}/include" + LDFLAGS="$LDFLAGS -L${withval}/lib" + fi + + if test -z "$KRB4" ; then + AC_MSG_WARN([AFS requires Kerberos IV support, build may fail]) + fi + + LIBS="-lkafs $LIBS" + if test ! -z "$AFS_LIBS" ; then + LIBS="$LIBS $AFS_LIBS" + fi + AC_DEFINE(AFS) + AFS_MSG="yes" + fi + ] +) +LIBS="$LIBS $KLIBS $K5LIBS" + +# Looking for programs, paths and files + +PRIVSEP_PATH=/var/empty +AC_ARG_WITH(privsep-path, + [ --with-privsep-path=xxx Path for privilege separation chroot ], + [ + if test "x$withval" != "$no" ; then + PRIVSEP_PATH=$withval + fi + ] +) +AC_SUBST(PRIVSEP_PATH) + +AC_ARG_WITH(xauth, + [ --with-xauth=PATH Specify path to xauth program ], + [ + if test "x$withval" != "xno" ; then + xauth_path=$withval + fi + ], + [ + AC_PATH_PROG(xauth_path, xauth,,$PATH:/usr/X/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/openwin/bin) + if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then + xauth_path="/usr/openwin/bin/xauth" + fi + ] +) + +if test -z "$xauth_path" ; then + XAUTH_PATH="undefined" + AC_SUBST(XAUTH_PATH) +else + AC_DEFINE_UNQUOTED(XAUTH_PATH, "$xauth_path") + XAUTH_PATH=$xauth_path + AC_SUBST(XAUTH_PATH) +fi + +# Check for mail directory (last resort if we cannot get it from headers) +if test ! -z "$MAIL" ; then + maildir=`dirname $MAIL` + AC_DEFINE_UNQUOTED(MAIL_DIRECTORY, "$maildir") +fi + +if test -z "$no_dev_ptmx" ; then + if test "x$disable_ptmx_check" != "xyes" ; then + AC_CHECK_FILE("/dev/ptmx", + [ + AC_DEFINE_UNQUOTED(HAVE_DEV_PTMX) + have_dev_ptmx=1 + ] + ) + fi +fi +AC_CHECK_FILE("/dev/ptc", + [ + AC_DEFINE_UNQUOTED(HAVE_DEV_PTS_AND_PTC) + have_dev_ptc=1 + ] +) + +# Options from here on. Some of these are preset by platform above +AC_ARG_WITH(mantype, + [ --with-mantype=man|cat|doc Set man page type], + [ + case "$withval" in + man|cat|doc) + MANTYPE=$withval + ;; + *) + AC_MSG_ERROR(invalid man type: $withval) + ;; + esac + ] +) +if test -z "$MANTYPE"; then + AC_PATH_PROGS(NROFF, nroff awf, /bin/false, /usr/bin:/usr/ucb) + if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then + MANTYPE=doc + elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then + MANTYPE=man + else + MANTYPE=cat + fi +fi +AC_SUBST(MANTYPE) +if test "$MANTYPE" = "doc"; then + mansubdir=man; +else + mansubdir=$MANTYPE; +fi +AC_SUBST(mansubdir) + +# Check whether to enable MD5 passwords +MD5_MSG="no" +AC_ARG_WITH(md5-passwords, + [ --with-md5-passwords Enable use of MD5 passwords], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE(HAVE_MD5_PASSWORDS) + MD5_MSG="yes" + fi + ] +) + +# Whether to disable shadow password support +AC_ARG_WITH(shadow, + [ --without-shadow Disable shadow password support], + [ + if test "x$withval" = "xno" ; then + AC_DEFINE(DISABLE_SHADOW) + disable_shadow=yes + fi + ] +) + +if test -z "$disable_shadow" ; then + AC_MSG_CHECKING([if the systems has expire shadow information]) + AC_TRY_COMPILE( + [ +#include +#include + struct spwd sp; + ],[ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ], + [ sp_expire_available=yes ], [] + ) + + if test "x$sp_expire_available" = "xyes" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAS_SHADOW_EXPIRE) + else + AC_MSG_RESULT(no) + fi +fi + +# Use ip address instead of hostname in $DISPLAY +if test ! -z "$IPADDR_IN_DISPLAY" ; then + DISPLAY_HACK_MSG="yes" + AC_DEFINE(IPADDR_IN_DISPLAY) +else + DISPLAY_HACK_MSG="no" + AC_ARG_WITH(ipaddr-display, + [ --with-ipaddr-display Use ip address instead of hostname in \$DISPLAY], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE(IPADDR_IN_DISPLAY) + DISPLAY_HACK_MSG="yes" + fi + ] + ) +fi + +dnl BSD systems use /etc/login.conf so --with-default-path= has no effect +if test $ac_cv_func_login_getcapbool = "yes" -a \ + $ac_cv_header_login_cap_h = "yes" ; then + USES_LOGIN_CONF=yes +fi +# Whether to mess with the default path +SERVER_PATH_MSG="(default)" +AC_ARG_WITH(default-path, + [ --with-default-path= Specify default \$PATH environment for server], + [ + if test "$USES_LOGIN_CONF" = "yes" ; then + AC_MSG_WARN([ +--with-default-path=PATH has no effect on this system. +Edit /etc/login.conf instead.]) + elif test "x$withval" != "xno" ; then + user_path="$withval" + SERVER_PATH_MSG="$withval" + fi + ], + [ if test "$USES_LOGIN_CONF" = "yes" ; then + AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf]) + else + AC_TRY_RUN( + [ +/* find out what STDPATH is */ +#include +#ifdef HAVE_PATHS_H +# include +#endif +#ifndef _PATH_STDPATH +# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" +#endif +#include +#include +#include +#define DATA "conftest.stdpath" + +main() +{ + FILE *fd; + int rc; + + fd = fopen(DATA,"w"); + if(fd == NULL) + exit(1); + + if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0) + exit(1); + + exit(0); +} + ], [ user_path=`cat conftest.stdpath` ], + [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ], + [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ] + ) +# make sure $bindir is in USER_PATH so scp will work + t_bindir=`eval echo ${bindir}` + case $t_bindir in + NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;; + esac + case $t_bindir in + NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;; + esac + echo $user_path | grep ":$t_bindir" > /dev/null 2>&1 + if test $? -ne 0 ; then + echo $user_path | grep "^$t_bindir" > /dev/null 2>&1 + if test $? -ne 0 ; then + user_path=$user_path:$t_bindir + AC_MSG_RESULT(Adding $t_bindir to USER_PATH so scp will work) + fi + fi + fi ] +) +if test "$USES_LOGIN_CONF" != "yes" ; then + AC_DEFINE_UNQUOTED(USER_PATH, "$user_path") + AC_SUBST(user_path) +fi + +# Set superuser path separately to user path +AC_ARG_WITH(superuser-path, + [ --with-superuser-path= Specify different path for super-user], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE_UNQUOTED(SUPERUSER_PATH, "$withval") + superuser_path=$withval + fi + ] +) + + +# Whether to force IPv4 by default (needed on broken glibc Linux) +IPV4_HACK_MSG="no" +AC_ARG_WITH(ipv4-default, + [ --with-ipv4-default Use IPv4 by connections unless '-6' specified], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE(IPV4_DEFAULT) + IPV4_HACK_MSG="yes" + fi + ] +) + +AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses]) +IPV4_IN6_HACK_MSG="no" +AC_ARG_WITH(4in6, + [ --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses], + [ + if test "x$withval" != "xno" ; then + AC_MSG_RESULT(yes) + AC_DEFINE(IPV4_IN_IPV6) + IPV4_IN6_HACK_MSG="yes" + else + AC_MSG_RESULT(no) + fi + ],[ + if test "x$inet6_default_4in6" = "xyes"; then + AC_MSG_RESULT([yes (default)]) + AC_DEFINE(IPV4_IN_IPV6) + IPV4_IN6_HACK_MSG="yes" + else + AC_MSG_RESULT([no (default)]) + fi + ] +) + +# Whether to enable BSD auth support +BSD_AUTH_MSG=no +AC_ARG_WITH(bsd-auth, + [ --with-bsd-auth Enable BSD auth support], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE(BSD_AUTH) + BSD_AUTH_MSG=yes + fi + ] +) + +# Where to place sshd.pid +piddir=/var/run +# make sure the directory exists +if test ! -d $piddir ; then + piddir=`eval echo ${sysconfdir}` + case $piddir in + NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; + esac +fi + +AC_ARG_WITH(pid-dir, + [ --with-pid-dir=PATH Specify location of ssh.pid file], + [ + if test "x$withval" != "xno" ; then + piddir=$withval + if test ! -d $piddir ; then + AC_MSG_WARN([** no $piddir directory on this system **]) + fi + fi + ] +) + +AC_DEFINE_UNQUOTED(_PATH_SSH_PIDDIR, "$piddir") +AC_SUBST(piddir) + +dnl allow user to disable some login recording features +AC_ARG_ENABLE(lastlog, + [ --disable-lastlog disable use of lastlog even if detected [no]], + [ AC_DEFINE(DISABLE_LASTLOG) ] +) +AC_ARG_ENABLE(utmp, + [ --disable-utmp disable use of utmp even if detected [no]], + [ AC_DEFINE(DISABLE_UTMP) ] +) +AC_ARG_ENABLE(utmpx, + [ --disable-utmpx disable use of utmpx even if detected [no]], + [ AC_DEFINE(DISABLE_UTMPX) ] +) +AC_ARG_ENABLE(wtmp, + [ --disable-wtmp disable use of wtmp even if detected [no]], + [ AC_DEFINE(DISABLE_WTMP) ] +) +AC_ARG_ENABLE(wtmpx, + [ --disable-wtmpx disable use of wtmpx even if detected [no]], + [ AC_DEFINE(DISABLE_WTMPX) ] +) +AC_ARG_ENABLE(libutil, + [ --disable-libutil disable use of libutil (login() etc.) [no]], + [ AC_DEFINE(DISABLE_LOGIN) ] +) +AC_ARG_ENABLE(pututline, + [ --disable-pututline disable use of pututline() etc. ([uw]tmp) [no]], + [ AC_DEFINE(DISABLE_PUTUTLINE) ] +) +AC_ARG_ENABLE(pututxline, + [ --disable-pututxline disable use of pututxline() etc. ([uw]tmpx) [no]], + [ AC_DEFINE(DISABLE_PUTUTXLINE) ] +) +AC_ARG_WITH(lastlog, + [ --with-lastlog=FILE|DIR specify lastlog location [common locations]], + [ + if test "x$withval" = "xno" ; then + AC_DEFINE(DISABLE_LASTLOG) + else + conf_lastlog_location=$withval + fi + ] +) + +dnl lastlog, [uw]tmpx? detection +dnl NOTE: set the paths in the platform section to avoid the +dnl need for command-line parameters +dnl lastlog and [uw]tmp are subject to a file search if all else fails + +dnl lastlog detection +dnl NOTE: the code itself will detect if lastlog is a directory +AC_MSG_CHECKING([if your system defines LASTLOG_FILE]) +AC_TRY_COMPILE([ +#include +#include +#ifdef HAVE_LASTLOG_H +# include +#endif +#ifdef HAVE_PATHS_H +# include +#endif +#ifdef HAVE_LOGIN_H +# include +#endif + ], + [ char *lastlog = LASTLOG_FILE; ], + [ AC_MSG_RESULT(yes) ], + [ + AC_MSG_RESULT(no) + AC_MSG_CHECKING([if your system defines _PATH_LASTLOG]) + AC_TRY_COMPILE([ +#include +#include +#ifdef HAVE_LASTLOG_H +# include +#endif +#ifdef HAVE_PATHS_H +# include +#endif + ], + [ char *lastlog = _PATH_LASTLOG; ], + [ AC_MSG_RESULT(yes) ], + [ + AC_MSG_RESULT(no) + system_lastlog_path=no + ]) + ] +) + +if test -z "$conf_lastlog_location"; then + if test x"$system_lastlog_path" = x"no" ; then + for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do + if (test -d "$f" || test -f "$f") ; then + conf_lastlog_location=$f + fi + done + if test -z "$conf_lastlog_location"; then + AC_MSG_WARN([** Cannot find lastlog **]) + dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx + fi + fi +fi + +if test -n "$conf_lastlog_location"; then + AC_DEFINE_UNQUOTED(CONF_LASTLOG_FILE, "$conf_lastlog_location") +fi + +dnl utmp detection +AC_MSG_CHECKING([if your system defines UTMP_FILE]) +AC_TRY_COMPILE([ +#include +#include +#ifdef HAVE_PATHS_H +# include +#endif + ], + [ char *utmp = UTMP_FILE; ], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + system_utmp_path=no ] +) +if test -z "$conf_utmp_location"; then + if test x"$system_utmp_path" = x"no" ; then + for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do + if test -f $f ; then + conf_utmp_location=$f + fi + done + if test -z "$conf_utmp_location"; then + AC_DEFINE(DISABLE_UTMP) + fi + fi +fi +if test -n "$conf_utmp_location"; then + AC_DEFINE_UNQUOTED(CONF_UTMP_FILE, "$conf_utmp_location") +fi + +dnl wtmp detection +AC_MSG_CHECKING([if your system defines WTMP_FILE]) +AC_TRY_COMPILE([ +#include +#include +#ifdef HAVE_PATHS_H +# include +#endif + ], + [ char *wtmp = WTMP_FILE; ], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + system_wtmp_path=no ] +) +if test -z "$conf_wtmp_location"; then + if test x"$system_wtmp_path" = x"no" ; then + for f in /usr/adm/wtmp /var/log/wtmp; do + if test -f $f ; then + conf_wtmp_location=$f + fi + done + if test -z "$conf_wtmp_location"; then + AC_DEFINE(DISABLE_WTMP) + fi + fi +fi +if test -n "$conf_wtmp_location"; then + AC_DEFINE_UNQUOTED(CONF_WTMP_FILE, "$conf_wtmp_location") +fi + + +dnl utmpx detection - I don't know any system so perverse as to require +dnl utmpx, but not define UTMPX_FILE (ditto wtmpx.) No doubt it's out +dnl there, though. +AC_MSG_CHECKING([if your system defines UTMPX_FILE]) +AC_TRY_COMPILE([ +#include +#include +#ifdef HAVE_UTMPX_H +#include +#endif +#ifdef HAVE_PATHS_H +# include +#endif + ], + [ char *utmpx = UTMPX_FILE; ], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + system_utmpx_path=no ] +) +if test -z "$conf_utmpx_location"; then + if test x"$system_utmpx_path" = x"no" ; then + AC_DEFINE(DISABLE_UTMPX) + fi +else + AC_DEFINE_UNQUOTED(CONF_UTMPX_FILE, "$conf_utmpx_location") +fi + +dnl wtmpx detection +AC_MSG_CHECKING([if your system defines WTMPX_FILE]) +AC_TRY_COMPILE([ +#include +#include +#ifdef HAVE_UTMPX_H +#include +#endif +#ifdef HAVE_PATHS_H +# include +#endif + ], + [ char *wtmpx = WTMPX_FILE; ], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + system_wtmpx_path=no ] +) +if test -z "$conf_wtmpx_location"; then + if test x"$system_wtmpx_path" = x"no" ; then + AC_DEFINE(DISABLE_WTMPX) + fi +else + AC_DEFINE_UNQUOTED(CONF_WTMPX_FILE, "$conf_wtmpx_location") +fi + + +if test ! -z "$blibpath" ; then + LDFLAGS="$LDFLAGS -blibpath:$blibpath" + AC_MSG_WARN([Please check and edit -blibpath in LDFLAGS in Makefile]) +fi + +dnl remove pam and dl because they are in $LIBPAM +if test "$PAM_MSG" = yes ; then + LIBS=`echo $LIBS | sed 's/-lpam //'` +fi +if test "$ac_cv_lib_pam_pam_set_item" = yes ; then + LIBS=`echo $LIBS | sed 's/-ldl //'` +fi + +AC_EXEEXT +AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds]) +AC_OUTPUT + +# Print summary of options + +# Someone please show me a better way :) +A=`eval echo ${prefix}` ; A=`eval echo ${A}` +B=`eval echo ${bindir}` ; B=`eval echo ${B}` +C=`eval echo ${sbindir}` ; C=`eval echo ${C}` +D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}` +E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}` +F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}` +G=`eval echo ${piddir}` ; G=`eval echo ${G}` +H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}` +I=`eval echo ${user_path}` ; I=`eval echo ${I}` +J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` + +echo "" +echo "OpenSSH has been configured with the following options:" +echo " User binaries: $B" +echo " System binaries: $C" +echo " Configuration files: $D" +echo " Askpass program: $E" +echo " Manual pages: $F" +echo " PID file: $G" +echo " Privilege separation chroot path: $H" +if test "$USES_LOGIN_CONF" = "yes" ; then +echo " At runtime, sshd will use the path defined in /etc/login.conf" +else +echo " sshd default user PATH: $I" +fi +if test ! -z "$superuser_path" ; then +echo " sshd superuser user PATH: $J" +fi +echo " Manpage format: $MANTYPE" +echo " PAM support: ${PAM_MSG}" +echo " KerberosIV support: $KRB4_MSG" +echo " KerberosV support: $KRB5_MSG" +echo " Smartcard support: $SCARD_MSG" +echo " AFS support: $AFS_MSG" +echo " S/KEY support: $SKEY_MSG" +echo " OPIE support: $OPIE_MSG" +echo " TCP Wrappers support: $TCPW_MSG" +echo " MD5 password support: $MD5_MSG" +echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" +echo " Use IPv4 by default hack: $IPV4_HACK_MSG" +echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" +echo " BSD Auth support: $BSD_AUTH_MSG" +echo " Random number source: $RAND_MSG" +if test ! -z "$USE_RAND_HELPER" ; then +echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" +fi + +echo "" + +echo " Host: ${host}" +echo " Compiler: ${CC}" +echo " Compiler flags: ${CFLAGS}" +echo "Preprocessor flags: ${CPPFLAGS}" +echo " Linker flags: ${LDFLAGS}" +echo " Libraries: ${LIBWRAP} ${LIBPAM} ${LIBS}" + +echo "" + +if test "x$PAM_MSG" = "xyes" ; then + echo "PAM is enabled. You may need to install a PAM control file " + echo "for sshd, otherwise password authentication may fail. " + echo "Example PAM control files can be found in the contrib/ " + echo "subdirectory" + echo "" +fi + +if test ! -z "$NO_SFTP"; then + echo "sftp-server will be disabled. Your compiler does not " + echo "support 64bit integers." + echo "" +fi + +if test ! -z "$RAND_HELPER_CMDHASH" ; then + echo "WARNING: you are using the builtin random number collection " + echo "service. Please read WARNING.RNG and request that your OS " + echo "vendor includes kernel-based random number collection in " + echo "future versions of your OS." + echo "" +fi + Index: src/crypto/openssh/crc32.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/crc32.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 crc32.h --- src/crypto/openssh/crc32.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/crc32.h 30 Jun 2002 11:37:58 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: crc32.h,v 1.13 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1992 Tatu Ylonen , Espoo, Finland @@ -11,15 +13,9 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: crc32.h,v 1.10 2001/03/02 18:54:31 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. - */ -u_int ssh_crc32(const u_char *buf, u_int len); +u_int ssh_crc32(const u_char *, u_int); #endif /* CRC32_H */ Index: src/crypto/openssh/deattack.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/deattack.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 deattack.c --- src/crypto/openssh/deattack.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/deattack.c 30 Jun 2002 11:37:58 -0000 @@ -1,5 +1,3 @@ -/* $OpenBSD: deattack.c,v 1.13 2001/03/01 02:45:10 deraadt Exp $ */ - /* * Cryptographic attack detector for ssh - source code * @@ -20,11 +18,14 @@ */ #include "includes.h" +RCSID("$OpenBSD: deattack.c,v 1.18 2002/03/04 17:27:39 stevesk Exp $"); + #include "deattack.h" #include "log.h" #include "crc32.h" #include "getput.h" #include "xmalloc.h" +#include "deattack.h" /* SSH Constants */ #define SSH_MAXBLOCKS (32 * 1024) @@ -36,7 +37,7 @@ #define HASH_FACTOR(x) ((x)*3/2) #define HASH_UNUSEDCHAR (0xff) #define HASH_UNUSED (0xffff) -#define HASH_IV (0xfffe) +#define HASH_IV (0xfffe) #define HASH_MINBLOCKS (7*SSH_BLOCKSIZE) @@ -46,8 +47,7 @@ #define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE)) - -void +static void crc_update(u_int32_t *a, u_int32_t b) { b ^= *a; @@ -55,7 +55,7 @@ } /* detect if a block is used in a particular pattern */ -int +static int check_crc(u_char *S, u_char *buf, u_int32_t len, u_char *IV) { @@ -86,9 +86,9 @@ { static u_int16_t *h = (u_int16_t *) NULL; static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE; - register u_int32_t i, j; + u_int32_t i, j; u_int32_t l; - register u_char *c; + u_char *c; u_char *d; if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || @@ -135,7 +135,7 @@ for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED; - i = (i + 1) & (n - 1)) { + i = (i + 1) & (n - 1)) { if (h[i] == HASH_IV) { if (!CMP(c, IV)) { if (check_crc(c, buf, len, IV)) Index: src/crypto/openssh/deattack.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/deattack.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 deattack.h --- src/crypto/openssh/deattack.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/deattack.h 30 Jun 2002 11:37:58 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: deattack.h,v 1.5 2001/01/29 01:58:15 niklas Exp $ */ +/* $OpenBSD: deattack.h,v 1.7 2001/06/26 17:27:23 markus Exp $ */ /* * Cryptographic attack detector for ssh - Header file @@ -26,5 +26,5 @@ #define DEATTACK_OK 0 #define DEATTACK_DETECTED 1 -int detect_attack(u_char *buf, u_int32_t len, u_char IV[8]); +int detect_attack(u_char *, u_int32_t, u_char[8]); #endif Index: src/crypto/openssh/defines.h =================================================================== RCS file: src/crypto/openssh/defines.h diff -N src/crypto/openssh/defines.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/defines.h 30 Jun 2002 11:37:58 -0000 @@ -0,0 +1,545 @@ +#ifndef _DEFINES_H +#define _DEFINES_H + +/* $Id$ */ + + +/* Constants */ + +#ifndef SHUT_RDWR +enum +{ + SHUT_RD = 0, /* No more receptions. */ + SHUT_WR, /* No more transmissions. */ + SHUT_RDWR /* No more receptions or transmissions. */ +}; +# define SHUT_RD SHUT_RD +# define SHUT_WR SHUT_WR +# define SHUT_RDWR SHUT_RDWR +#endif + +#ifndef IPTOS_LOWDELAY +# define IPTOS_LOWDELAY 0x10 +# define IPTOS_THROUGHPUT 0x08 +# define IPTOS_RELIABILITY 0x04 +# define IPTOS_LOWCOST 0x02 +# define IPTOS_MINCOST IPTOS_LOWCOST +#endif /* IPTOS_LOWDELAY */ + +#ifndef MAXPATHLEN +# ifdef PATH_MAX +# define MAXPATHLEN PATH_MAX +# else /* PATH_MAX */ +# define MAXPATHLEN 64 /* Should be safe */ +# endif /* PATH_MAX */ +#endif /* MAXPATHLEN */ + +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +#ifndef NGROUPS_MAX /* Disable groupaccess if NGROUP_MAX is not set */ +#ifdef NGROUPS +#define NGROUPS_MAX NGROUPS +#else +#define NGROUPS_MAX 0 +#endif +#endif + +#ifndef O_NONBLOCK /* Non Blocking Open */ +# define O_NONBLOCK 00004 +#endif + +#ifndef S_ISDIR +# define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR)) +#endif /* S_ISDIR */ + +#ifndef S_ISREG +# define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG)) +#endif /* S_ISREG */ + +#ifndef S_ISLNK +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif /* S_ISLNK */ + +#ifndef S_IXUSR +# define S_IXUSR 0000100 /* execute/search permission, */ +# define S_IXGRP 0000010 /* execute/search permission, */ +# define S_IXOTH 0000001 /* execute/search permission, */ +# define _S_IWUSR 0000200 /* write permission, */ +# define S_IWUSR _S_IWUSR /* write permission, owner */ +# define S_IWGRP 0000020 /* write permission, group */ +# define S_IWOTH 0000002 /* write permission, other */ +# define S_IRUSR 0000400 /* read permission, owner */ +# define S_IRGRP 0000040 /* read permission, group */ +# define S_IROTH 0000004 /* read permission, other */ +# define S_IRWXU 0000700 /* read, write, execute */ +# define S_IRWXG 0000070 /* read, write, execute */ +# define S_IRWXO 0000007 /* read, write, execute */ +#endif /* S_IXUSR */ + +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +#define MAP_ANON MAP_ANONYMOUS +#endif + +#ifndef MAP_FAILED +# define MAP_FAILED ((void *)-1) +#endif + +/* *-*-nto-qnx doesn't define this constant in the system headers */ +#ifdef MISSING_NFDBITS +# define NFDBITS (8 * sizeof(unsigned long)) +#endif + +/* +SCO Open Server 3 has INADDR_LOOPBACK defined in rpc/rpc.h but +including rpc/rpc.h breaks Solaris 6 +*/ +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK ((ulong)0x7f000001) +#endif + +/* Types */ + +/* If sys/types.h does not supply intXX_t, supply them ourselves */ +/* (or die trying) */ + + +#ifndef HAVE_U_INT +typedef unsigned int u_int; +#endif + +#ifndef HAVE_INTXX_T +# if (SIZEOF_CHAR == 1) +typedef char int8_t; +# else +# error "8 bit int type not found." +# endif +# if (SIZEOF_SHORT_INT == 2) +typedef short int int16_t; +# else +# ifdef _CRAY +# if (SIZEOF_SHORT_INT == 4) +typedef short int16_t; +# else +typedef long int16_t; +# endif +# else +# error "16 bit int type not found." +# endif /* _CRAY */ +# endif +# if (SIZEOF_INT == 4) +typedef int int32_t; +# else +# ifdef _CRAY +typedef long int32_t; +# else +# error "32 bit int type not found." +# endif /* _CRAY */ +# endif +#endif + +/* If sys/types.h does not supply u_intXX_t, supply them ourselves */ +#ifndef HAVE_U_INTXX_T +# ifdef HAVE_UINTXX_T +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +# define HAVE_U_INTXX_T 1 +# else +# if (SIZEOF_CHAR == 1) +typedef unsigned char u_int8_t; +# else +# error "8 bit int type not found." +# endif +# if (SIZEOF_SHORT_INT == 2) +typedef unsigned short int u_int16_t; +# else +# ifdef _CRAY +# if (SIZEOF_SHORT_INT == 4) +typedef unsigned short u_int16_t; +# else +typedef unsigned long u_int16_t; +# endif +# else +# error "16 bit int type not found." +# endif +# endif +# if (SIZEOF_INT == 4) +typedef unsigned int u_int32_t; +# else +# ifdef _CRAY +typedef unsigned long u_int32_t; +# else +# error "32 bit int type not found." +# endif +# endif +# endif +#define __BIT_TYPES_DEFINED__ +#endif + +/* 64-bit types */ +#ifndef HAVE_INT64_T +# if (SIZEOF_LONG_INT == 8) +typedef long int int64_t; +# define HAVE_INT64_T 1 +# else +# if (SIZEOF_LONG_LONG_INT == 8) +typedef long long int int64_t; +# define HAVE_INT64_T 1 +# endif +# endif +#endif +#ifndef HAVE_U_INT64_T +# if (SIZEOF_LONG_INT == 8) +typedef unsigned long int u_int64_t; +# define HAVE_U_INT64_T 1 +# else +# if (SIZEOF_LONG_LONG_INT == 8) +typedef unsigned long long int u_int64_t; +# define HAVE_U_INT64_T 1 +# endif +# endif +#endif +#if !defined(HAVE_LONG_LONG_INT) && (SIZEOF_LONG_LONG_INT == 8) +# define HAVE_LONG_LONG_INT 1 +#endif + +#ifndef HAVE_U_CHAR +typedef unsigned char u_char; +# define HAVE_U_CHAR +#endif /* HAVE_U_CHAR */ + +#ifndef HAVE_SIZE_T +typedef unsigned int size_t; +# define HAVE_SIZE_T +#endif /* HAVE_SIZE_T */ + +#ifndef HAVE_SSIZE_T +typedef int ssize_t; +# define HAVE_SSIZE_T +#endif /* HAVE_SSIZE_T */ + +#ifndef HAVE_CLOCK_T +typedef long clock_t; +# define HAVE_CLOCK_T +#endif /* HAVE_CLOCK_T */ + +#ifndef HAVE_SA_FAMILY_T +typedef int sa_family_t; +# define HAVE_SA_FAMILY_T +#endif /* HAVE_SA_FAMILY_T */ + +#ifndef HAVE_PID_T +typedef int pid_t; +# define HAVE_PID_T +#endif /* HAVE_PID_T */ + +#ifndef HAVE_SIG_ATOMIC_T +typedef int sig_atomic_t; +# define HAVE_SIG_ATOMIC_T +#endif /* HAVE_SIG_ATOMIC_T */ + +#ifndef HAVE_MODE_T +typedef int mode_t; +# define HAVE_MODE_T +#endif /* HAVE_MODE_T */ + +#if !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE___SS_FAMILY_IN_SS) +# define ss_family __ss_family +#endif /* !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE_SA_FAMILY_IN_SS) */ + +#ifndef HAVE_SYS_UN_H +struct sockaddr_un { + short sun_family; /* AF_UNIX */ + char sun_path[108]; /* path name (gag) */ +}; +#endif /* HAVE_SYS_UN_H */ + +#if defined(BROKEN_SYS_TERMIO_H) && !defined(_STRUCT_WINSIZE) +#define _STRUCT_WINSIZE +struct winsize { + unsigned short ws_row; /* rows, in characters */ + unsigned short ws_col; /* columns, in character */ + unsigned short ws_xpixel; /* horizontal size, pixels */ + unsigned short ws_ypixel; /* vertical size, pixels */ +}; +#endif + +/* *-*-nto-qnx does not define this type in the system headers */ +#ifdef MISSING_FD_MASK + typedef unsigned long int fd_mask; +#endif + +/* Paths */ + +#ifndef _PATH_BSHELL +# define _PATH_BSHELL "/bin/sh" +#endif +#ifndef _PATH_CSHELL +# define _PATH_CSHELL "/bin/csh" +#endif +#ifndef _PATH_SHELLS +# define _PATH_SHELLS "/etc/shells" +#endif + +#ifdef USER_PATH +# ifdef _PATH_STDPATH +# undef _PATH_STDPATH +# endif +# define _PATH_STDPATH USER_PATH +#endif + +#ifndef _PATH_STDPATH +# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" +#endif + +#ifndef _PATH_DEVNULL +# define _PATH_DEVNULL "/dev/null" +#endif + +#ifndef MAIL_DIRECTORY +# define MAIL_DIRECTORY "/var/spool/mail" +#endif + +#ifndef MAILDIR +# define MAILDIR MAIL_DIRECTORY +#endif + +#if !defined(_PATH_MAILDIR) && defined(MAILDIR) +# define _PATH_MAILDIR MAILDIR +#endif /* !defined(_PATH_MAILDIR) && defined(MAILDIR) */ + +#ifndef _PATH_NOLOGIN +# define _PATH_NOLOGIN "/etc/nologin" +#endif + +/* Define this to be the path of the xauth program. */ +#ifdef XAUTH_PATH +#define _PATH_XAUTH XAUTH_PATH +#endif /* XAUTH_PATH */ + +/* derived from XF4/xc/lib/dps/Xlibnet.h */ +#ifndef X_UNIX_PATH +# ifdef __hpux +# define X_UNIX_PATH "/var/spool/sockets/X11/%u" +# else +# define X_UNIX_PATH "/tmp/.X11-unix/X%u" +# endif +#endif /* X_UNIX_PATH */ +#define _PATH_UNIX_X X_UNIX_PATH + +#ifndef _PATH_TTY +# define _PATH_TTY "/dev/tty" +#endif + +/* Macros */ + +#if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H) +# define HAVE_LOGIN_CAP +#endif + +#ifndef MAX +# define MAX(a,b) (((a)>(b))?(a):(b)) +# define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef roundup +# define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + +#ifndef timersub +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + +#ifndef __P +# define __P(x) x +#endif + +#if !defined(IN6_IS_ADDR_V4MAPPED) +# define IN6_IS_ADDR_V4MAPPED(a) \ + ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \ + (((u_int32_t *) (a))[2] == htonl (0xffff))) +#endif /* !defined(IN6_IS_ADDR_V4MAPPED) */ + +#if !defined(__GNUC__) || (__GNUC__ < 2) +# define __attribute__(x) +#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */ + +/* *-*-nto-qnx doesn't define this macro in the system headers */ +#ifdef MISSING_HOWMANY +# define howmany(x,y) (((x)+((y)-1))/(y)) +#endif + +#ifndef OSSH_ALIGNBYTES +#define OSSH_ALIGNBYTES (sizeof(int) - 1) +#endif +#ifndef __CMSG_ALIGN +#define __CMSG_ALIGN(p) (((u_int)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES) +#endif + +/* Length of the contents of a control message of length len */ +#ifndef CMSG_LEN +#define CMSG_LEN(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) +#endif + +/* Length of the space taken up by a padded control message of length len */ +#ifndef CMSG_SPACE +#define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len)) +#endif + +/* Function replacement / compatibility hacks */ + +#if !defined(HAVE_GETADDRINFO) && (defined(HAVE_OGETADDRINFO) || defined(HAVE_NGETADDRINFO)) +# define HAVE_GETADDRINFO +#endif + +#ifndef HAVE_GETOPT_OPTRESET +# undef getopt +# undef opterr +# undef optind +# undef optopt +# undef optreset +# undef optarg +# define getopt(ac, av, o) BSDgetopt(ac, av, o) +# define opterr BSDopterr +# define optind BSDoptind +# define optopt BSDoptopt +# define optreset BSDoptreset +# define optarg BSDoptarg +#endif + +/* In older versions of libpam, pam_strerror takes a single argument */ +#ifdef HAVE_OLD_PAM +# define PAM_STRERROR(a,b) pam_strerror((b)) +#else +# define PAM_STRERROR(a,b) pam_strerror((a),(b)) +#endif + +#ifdef PAM_SUN_CODEBASE +# define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member) +#else +# define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member) +#endif + +#if defined(BROKEN_GETADDRINFO) && defined(HAVE_GETADDRINFO) +# undef HAVE_GETADDRINFO +#endif +#if defined(BROKEN_GETADDRINFO) && defined(HAVE_FREEADDRINFO) +# undef HAVE_FREEADDRINFO +#endif +#if defined(BROKEN_GETADDRINFO) && defined(HAVE_GAI_STRERROR) +# undef HAVE_GAI_STRERROR +#endif + +#if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) +# define memmove(s1, s2, n) bcopy((s2), (s1), (n)) +#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ + +#if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) +# define USE_VHANGUP +#endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */ + +#ifndef GETPGRP_VOID +# define getpgrp() getpgrp(0) +#endif + +/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */ +#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f) +# define OPENSSL_free(x) Free(x) +#endif + +#if !defined(HAVE___func__) && defined(HAVE___FUNCTION__) +# define __func__ __FUNCTION__ +#elif !defined(HAVE___func__) +# define __func__ "" +#endif + +/* + * Define this to use pipes instead of socketpairs for communicating with the + * client program. Socketpairs do not seem to work on all systems. + * + * configure.ac sets this for a few OS's which are known to have problems + * but you may need to set it yourself + */ +/* #define USE_PIPES 1 */ + +/** + ** login recorder definitions + **/ + +/* FIXME: put default paths back in */ +#ifndef UTMP_FILE +# ifdef _PATH_UTMP +# define UTMP_FILE _PATH_UTMP +# else +# ifdef CONF_UTMP_FILE +# define UTMP_FILE CONF_UTMP_FILE +# endif +# endif +#endif +#ifndef WTMP_FILE +# ifdef _PATH_WTMP +# define WTMP_FILE _PATH_WTMP +# else +# ifdef CONF_WTMP_FILE +# define WTMP_FILE CONF_WTMP_FILE +# endif +# endif +#endif +/* pick up the user's location for lastlog if given */ +#ifndef LASTLOG_FILE +# ifdef _PATH_LASTLOG +# define LASTLOG_FILE _PATH_LASTLOG +# else +# ifdef CONF_LASTLOG_FILE +# define LASTLOG_FILE CONF_LASTLOG_FILE +# endif +# endif +#endif + + +/* The login() library function in libutil is first choice */ +#if defined(HAVE_LOGIN) && !defined(DISABLE_LOGIN) +# define USE_LOGIN + +#else +/* Simply select your favourite login types. */ +/* Can't do if-else because some systems use several... */ +# if defined(UTMPX_FILE) && !defined(DISABLE_UTMPX) +# define USE_UTMPX +# endif +# if defined(UTMP_FILE) && !defined(DISABLE_UTMP) +# define USE_UTMP +# endif +# if defined(WTMPX_FILE) && !defined(DISABLE_WTMPX) +# define USE_WTMPX +# endif +# if defined(WTMP_FILE) && !defined(DISABLE_WTMP) +# define USE_WTMP +# endif + +#endif + +/* I hope that the presence of LASTLOG_FILE is enough to detect this */ +#if defined(LASTLOG_FILE) && !defined(DISABLE_LASTLOG) +# define USE_LASTLOG +#endif + +/** end of login recorder definitions */ + +#endif /* _DEFINES_H */ Index: src/crypto/openssh/dh.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/dh.c,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 dh.c --- src/crypto/openssh/dh.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/dh.c 30 Jun 2002 11:37:58 -0000 @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: dh.c,v 1.14 2001/04/15 08:43:45 markus Exp $"); +RCSID("$OpenBSD: dh.c,v 1.21 2002/03/06 00:23:27 markus Exp $"); #include "xmalloc.h" @@ -39,7 +39,7 @@ #include "log.h" #include "misc.h" -int +static int parse_prime(int linenum, char *line, struct dhgroup *dhg) { char *cp, *arg; @@ -78,8 +78,10 @@ if (cp != NULL || *prime == '\0') goto fail; - dhg->g = BN_new(); - dhg->p = BN_new(); + if ((dhg->g = BN_new()) == NULL) + fatal("parse_prime: BN_new failed"); + if ((dhg->p = BN_new()) == NULL) + fatal("parse_prime: BN_new failed"); if (BN_hex2bn(&dhg->g, gen) == 0) goto failclean; @@ -92,8 +94,8 @@ return (1); failclean: - BN_free(dhg->g); - BN_free(dhg->p); + BN_clear_free(dhg->g); + BN_clear_free(dhg->p); fail: error("Bad prime description in line %d", linenum); return (0); @@ -103,14 +105,14 @@ choose_dh(int min, int wantbits, int max) { FILE *f; - char line[1024]; + char line[2048]; int best, bestcount, which; int linenum; struct dhgroup dhg; - f = fopen(_PATH_DH_PRIMES, "r"); - if (!f) { - log("WARNING: %s does not exist, using old prime", _PATH_DH_PRIMES); + if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL && + (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) { + log("WARNING: %s does not exist, using old modulus", _PATH_DH_MODULI); return (dh_new_group1()); } @@ -120,8 +122,8 @@ linenum++; if (!parse_prime(linenum, line, &dhg)) continue; - BN_free(dhg.g); - BN_free(dhg.p); + BN_clear_free(dhg.g); + BN_clear_free(dhg.p); if (dhg.size > max || dhg.size < min) continue; @@ -134,18 +136,14 @@ if (dhg.size == best) bestcount++; } - fclose (f); + rewind(f); if (bestcount == 0) { + fclose(f); log("WARNING: no suitable primes in %s", _PATH_DH_PRIMES); return (NULL); } - f = fopen(_PATH_DH_PRIMES, "r"); - if (!f) { - fatal("WARNING: %s disappeared, giving up", _PATH_DH_PRIMES); - } - linenum = 0; which = arc4random() % bestcount; while (fgets(line, sizeof(line), f)) { @@ -154,8 +152,8 @@ if ((dhg.size > max || dhg.size < min) || dhg.size != best || linenum++ != which) { - BN_free(dhg.g); - BN_free(dhg.p); + BN_clear_free(dhg.g); + BN_clear_free(dhg.p); continue; } break; @@ -205,9 +203,8 @@ BN_num_bits(dh->p), 2*need); do { if (dh->priv_key != NULL) - BN_free(dh->priv_key); - dh->priv_key = BN_new(); - if (dh->priv_key == NULL) + BN_clear_free(dh->priv_key); + if ((dh->priv_key = BN_new()) == NULL) fatal("dh_gen_key: BN_new failed"); /* generate a 2*need bits random private exponent */ if (!BN_rand(dh->priv_key, 2*need, 0, 0)) @@ -229,9 +226,8 @@ { DH *dh; - dh = DH_new(); - if (dh == NULL) - fatal("DH_new"); + if ((dh = DH_new()) == NULL) + fatal("dh_new_group_asc: DH_new"); if (BN_hex2bn(&dh->p, modulus) == 0) fatal("BN_hex2bn p"); @@ -251,9 +247,8 @@ { DH *dh; - dh = DH_new(); - if (dh == NULL) - fatal("DH_new"); + if ((dh = DH_new()) == NULL) + fatal("dh_new_group: DH_new"); dh->p = modulus; dh->g = gen; Index: src/crypto/openssh/dh.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/dh.h,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 dh.h --- src/crypto/openssh/dh.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/dh.h 30 Jun 2002 11:37:58 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: dh.h,v 1.5 2001/04/03 19:53:29 markus Exp $ */ +/* $OpenBSD: dh.h,v 1.7 2001/06/26 17:27:23 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. @@ -32,15 +32,15 @@ BIGNUM *p; }; -DH *choose_dh(int min, int nbits, int max); +DH *choose_dh(int, int, int); DH *dh_new_group_asc(const char *, const char *); DH *dh_new_group(BIGNUM *, BIGNUM *); DH *dh_new_group1(void); -void dh_gen_key(DH *, int); -int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); +void dh_gen_key(DH *, int); +int dh_pub_is_valid(DH *, BIGNUM *); -int dh_estimate(int bits); +int dh_estimate(int); #define DH_GRP_MIN 1024 #define DH_GRP_MAX 8192 Index: src/crypto/openssh/dispatch.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/dispatch.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 dispatch.c --- src/crypto/openssh/dispatch.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/dispatch.c 30 Jun 2002 11:37:58 -0000 @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: dispatch.c,v 1.10 2001/02/18 18:33:53 markus Exp $"); +RCSID("$OpenBSD: dispatch.c,v 1.15 2002/01/11 13:39:36 markus Exp $"); #include "ssh1.h" #include "ssh2.h" @@ -37,20 +37,40 @@ dispatch_fn *dispatch[DISPATCH_MAX]; void -dispatch_protocol_error(int type, int plen, void *ctxt) +dispatch_protocol_error(int type, u_int32_t seq, void *ctxt) { - error("Hm, dispatch protocol error: type %d plen %d", type, plen); - if (compat20 && type == SSH2_MSG_KEXINIT) - fatal("dispatch_protocol_error: rekeying is not supported"); + log("dispatch_protocol_error: type %d seq %u", type, seq); + if (!compat20) + fatal("protocol error"); + packet_start(SSH2_MSG_UNIMPLEMENTED); + packet_put_int(seq); + packet_send(); + packet_write_wait(); +} +void +dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt) +{ + log("dispatch_protocol_ignore: type %d seq %u", type, seq); } void dispatch_init(dispatch_fn *dflt) { - int i; + u_int i; for (i = 0; i < DISPATCH_MAX; i++) dispatch[i] = dflt; } void +dispatch_range(u_int from, u_int to, dispatch_fn *fn) +{ + u_int i; + + for (i = from; i <= to; i++) { + if (i >= DISPATCH_MAX) + break; + dispatch[i] = fn; + } +} +void dispatch_set(int type, dispatch_fn *fn) { dispatch[type] = fn; @@ -59,18 +79,18 @@ dispatch_run(int mode, int *done, void *ctxt) { for (;;) { - int plen; int type; + u_int32_t seqnr; if (mode == DISPATCH_BLOCK) { - type = packet_read(&plen); + type = packet_read_seqnr(&seqnr); } else { - type = packet_read_poll(&plen); + type = packet_read_poll_seqnr(&seqnr); if (type == SSH_MSG_NONE) return; } if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL) - (*dispatch[type])(type, plen, ctxt); + (*dispatch[type])(type, seqnr, ctxt); else packet_disconnect("protocol error: rcvd type %d", type); if (done != NULL && *done) Index: src/crypto/openssh/dispatch.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/dispatch.h,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 dispatch.h --- src/crypto/openssh/dispatch.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/dispatch.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.h,v 1.4 2001/01/29 01:58:15 niklas Exp $ */ +/* $OpenBSD: dispatch.h,v 1.9 2002/01/11 13:39:36 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -28,9 +28,11 @@ DISPATCH_NONBLOCK }; -typedef void dispatch_fn(int type, int plen, void *ctxt); +typedef void dispatch_fn(int, u_int32_t, void *); -void dispatch_init(dispatch_fn *dflt); -void dispatch_set(int type, dispatch_fn *fn); -void dispatch_run(int mode, int *done, void *ctxt); -void dispatch_protocol_error(int type, int plen, void *ctxt); +void dispatch_init(dispatch_fn *); +void dispatch_set(int, dispatch_fn *); +void dispatch_range(u_int, u_int, dispatch_fn *); +void dispatch_run(int, int *, void *); +void dispatch_protocol_error(int, u_int32_t, void *); +void dispatch_protocol_ignore(int, u_int32_t, void *); Index: src/crypto/openssh/entropy.c =================================================================== RCS file: src/crypto/openssh/entropy.c diff -N src/crypto/openssh/entropy.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/entropy.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2001 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include +#include + +#include "ssh.h" +#include "misc.h" +#include "xmalloc.h" +#include "atomicio.h" +#include "pathnames.h" +#include "log.h" + +/* + * Portable OpenSSH PRNG seeding: + * If OpenSSL has not "internally seeded" itself (e.g. pulled data from + * /dev/random), then we execute a "ssh-rand-helper" program which + * collects entropy and writes it to stdout. The child program must + * write at least RANDOM_SEED_SIZE bytes. The child is run with stderr + * attached, so error/debugging output should be visible. + * + * XXX: we should tell the child how many bytes we need. + */ + +RCSID("$Id$"); + +#ifndef OPENSSL_PRNG_ONLY +#define RANDOM_SEED_SIZE 48 +static uid_t original_uid, original_euid; +#endif + +void +seed_rng(void) +{ +#ifndef OPENSSL_PRNG_ONLY + int devnull; + int p[2]; + pid_t pid; + int ret; + unsigned char buf[RANDOM_SEED_SIZE]; + mysig_t old_sigchld; + + if (RAND_status() == 1) { + debug3("RNG is ready, skipping seeding"); + return; + } + + debug3("Seeding PRNG from %s", SSH_RAND_HELPER); + + if ((devnull = open("/dev/null", O_RDWR)) == -1) + fatal("Couldn't open /dev/null: %s", strerror(errno)); + if (pipe(p) == -1) + fatal("pipe: %s", strerror(errno)); + + old_sigchld = mysignal(SIGCHLD, SIG_DFL); + if ((pid = fork()) == -1) + fatal("Couldn't fork: %s", strerror(errno)); + if (pid == 0) { + dup2(devnull, STDIN_FILENO); + dup2(p[1], STDOUT_FILENO); + /* Keep stderr open for errors */ + close(p[0]); + close(p[1]); + close(devnull); + + if (original_uid != original_euid && + ( seteuid(getuid()) == -1 || + setuid(original_uid) == -1) ) { + fprintf(stderr, "(rand child) setuid(%d): %s\n", + original_uid, strerror(errno)); + _exit(1); + } + + execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL); + fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n", + SSH_RAND_HELPER, strerror(errno)); + _exit(1); + } + + close(devnull); + close(p[1]); + + memset(buf, '\0', sizeof(buf)); + ret = atomicio(read, p[0], buf, sizeof(buf)); + if (ret == -1) + fatal("Couldn't read from ssh-rand-helper: %s", + strerror(errno)); + if (ret != sizeof(buf)) + fatal("ssh-rand-helper child produced insufficient data"); + + close(p[0]); + + if (waitpid(pid, &ret, 0) == -1) + fatal("Couldn't wait for ssh-rand-helper completion: %s", + strerror(errno)); + mysignal(SIGCHLD, old_sigchld); + + /* We don't mind if the child exits upon a SIGPIPE */ + if (!WIFEXITED(ret) && + (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE)) + fatal("ssh-rand-helper terminated abnormally"); + if (WEXITSTATUS(ret) != 0) + fatal("ssh-rand-helper exit with exit status %d", ret); + + RAND_add(buf, sizeof(buf), sizeof(buf)); + memset(buf, '\0', sizeof(buf)); + +#endif /* OPENSSL_PRNG_ONLY */ + if (RAND_status() != 1) + fatal("PRNG is not seeded"); +} + +void +init_rng(void) +{ + /* + * OpenSSL version numbers: MNNFFPPS: major minor fix patch status + * We match major, minor, fix and status (not patch) + */ + if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); + +#ifndef OPENSSL_PRNG_ONLY + if ((original_uid = getuid()) == -1) + fatal("getuid: %s", strerror(errno)); + if ((original_euid = geteuid()) == -1) + fatal("geteuid: %s", strerror(errno)); +#endif +} + Index: src/crypto/openssh/entropy.h =================================================================== RCS file: src/crypto/openssh/entropy.h diff -N src/crypto/openssh/entropy.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/entropy.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef _RANDOMS_H +#define _RANDOMS_H + +void seed_rng(void); +void init_rng(void); + +#endif /* _RANDOMS_H */ Index: src/crypto/openssh/fatal.c =================================================================== RCS file: src/crypto/openssh/fatal.c diff -N src/crypto/openssh/fatal.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/fatal.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: fatal.c,v 1.1 2002/02/22 12:20:34 markus Exp $"); + +#include "log.h" + +/* Fatal messages. This function never returns. */ + +void +fatal(const char *fmt,...) +{ + va_list args; + va_start(args, fmt); + do_log(SYSLOG_LEVEL_FATAL, fmt, args); + va_end(args); + fatal_cleanup(); +} Index: src/crypto/openssh/fixpaths =================================================================== RCS file: src/crypto/openssh/fixpaths diff -N src/crypto/openssh/fixpaths --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/fixpaths 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,43 @@ +#!/usr/bin/perl -w +# +# fixpaths - substitute makefile variables into text files + + +$usage = "Usage: $0 [-Dstring=replacement] [[infile] ...]\n"; + +if (!defined(@ARGV)) { die ("$usage"); } + +# read in the command line and get some definitions +while ($_=$ARGV[0], /^-/) { + if (/^-D/) { + # definition + shift(@ARGV); + if ( /-D(.*)=(.*)/ ) { + $def{"$1"}=$2; + } else { + die ("$usage$0: error in command line arguments.\n"); + } + } else { + @cmd = split(//, $ARGV[0]); $opt = $cmd[1]; + die ("$usage$0: unknown option '-$opt'\n"); + } +} # while parsing arguments + +if (!defined(%def)) { + die ("$0: nothing to do - no substitutions listed!\n"); +} + +for $f (@ARGV) { + + $f =~ /(.*\/)*(.*)$/; + + open(IN, "<$f") || die ("$0: input file $f missing!\n"); + while () { + for $s (keys(%def)) { + s#$s#$def{$s}#; + } # for $s + print; + } # while +} # for $f + +exit 0; Index: src/crypto/openssh/fixprogs =================================================================== RCS file: src/crypto/openssh/fixprogs diff -N src/crypto/openssh/fixprogs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/fixprogs 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,72 @@ +#!/usr/bin/perl +# +# fixprogs - run through the list of entropy commands and +# score out the losers +# + +$entscale = 50; # divisor for optional entropy measurement + +sub usage { + return("Usage: $0 \n"); +} + +if (($#ARGV == -1) || ($#ARGV>1)) { + die(&usage); +} + +# 'undocumented' option - run ent (in second param) on the output +if ($#ARGV==1) { + $entcmd=$ARGV[1] +} else { + $entcmd = "" +}; + +$infilename = $ARGV[0]; + +if (!open(IN, "<".$infilename)) { + die("Couldn't open input file"); +} +$outfilename=$infilename.".out"; +if (!open(OUT, ">$outfilename")) { + die("Couldn't open output file $outfilename"); +} +@infile=; + +select(OUT); $|=1; select(STDOUT); + +foreach (@infile) { + if (/^\s*\#/ || /^\s*$/) { + print OUT; + next; + } + ($cmd, $path, $est) = /^\"([^\"]+)\"\s+([\w\/_-]+)\s+([\d\.\-]+)/o; + @args = split(/ /, $cmd); + if (! ($pid = fork())) { + # child + close STDIN; close STDOUT; close STDERR; + open (STDIN, "/dev/null"); + open (STDERR, ">/dev/null"); + exec $path @args; + exit 1; # shouldn't be here + } + # parent + waitpid ($pid, 0); $ret=$? >> 8; + + if ($ret != 0) { + $path = "undef"; + } else { + if ($entcmd ne "") { + # now try to run ent on the command + $mostargs=join(" ", splice(@args,1)); + print "Evaluating '$path $mostargs'\n"; + @ent = qx{$path $mostargs | $entcmd -b -t}; + @ent = grep(/^1,/, @ent); + ($null, $null, $rate) = split(/,/, $ent[0]); + $est = $rate / $entscale; # scale the estimate back + } + } + print OUT "\"$cmd\" $path $est\n"; +} + +close(IN); Index: src/crypto/openssh/getput.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/getput.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 getput.h --- src/crypto/openssh/getput.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/getput.h 30 Jun 2002 11:37:59 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: getput.h,v 1.8 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,8 +12,6 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ - -/* RCSID("$OpenBSD: getput.h,v 1.7 2001/01/10 22:56:22 markus Exp $"); */ #ifndef GETPUT_H #define GETPUT_H Index: src/crypto/openssh/groupaccess.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/groupaccess.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 groupaccess.c --- src/crypto/openssh/groupaccess.c 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/groupaccess.c 30 Jun 2002 11:37:59 -0000 @@ -1,5 +1,3 @@ -/* $OpenBSD: groupaccess.c,v 1.3 2001/01/29 01:58:15 niklas Exp $ */ - /* * Copyright (c) 2001 Kevin Steves. All rights reserved. * @@ -25,6 +23,7 @@ */ #include "includes.h" +RCSID("$OpenBSD: groupaccess.c,v 1.5 2002/03/04 17:27:39 stevesk Exp $"); #include "groupaccess.h" #include "xmalloc.h" @@ -34,6 +33,10 @@ static int ngroups; static char *groups_byname[NGROUPS_MAX + 1]; /* +1 for base/primary group */ +/* + * Initialize group access list for user with primary (base) and + * supplementary groups. Return the number of groups in the list. + */ int ga_init(const char *user, gid_t base) { @@ -53,6 +56,10 @@ return (ngroups = j); } +/* + * Return 1 if one of user's groups is contained in groups. + * Return 0 otherwise. Use match_pattern() for string comparison. + */ int ga_match(char * const *groups, int n) { @@ -65,6 +72,9 @@ return 0; } +/* + * Free memory allocated for group access list. + */ void ga_free(void) { Index: src/crypto/openssh/groupaccess.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/groupaccess.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 groupaccess.h --- src/crypto/openssh/groupaccess.h 28 Sep 2001 01:33:33 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/groupaccess.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: groupaccess.h,v 1.2 2001/01/29 01:58:15 niklas Exp $ */ +/* $OpenBSD: groupaccess.h,v 1.4 2001/06/26 17:27:23 markus Exp $ */ /* * Copyright (c) 2001 Kevin Steves. All rights reserved. @@ -29,21 +29,8 @@ #include -/* - * Initialize group access list for user with primary (base) and - * supplementary groups. Return the number of groups in the list. - */ -int ga_init(const char *user, gid_t base); - -/* - * Return 1 if one of user's groups is contained in groups. - * Return 0 otherwise. Use match_pattern() for string comparison. - */ -int ga_match(char * const *groups, int ngroups); - -/* - * Free memory allocated for group access list. - */ -void ga_free(void); +int ga_init(const char *, gid_t); +int ga_match(char * const *, int); +void ga_free(void); #endif Index: src/crypto/openssh/hostfile.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/hostfile.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 hostfile.c --- src/crypto/openssh/hostfile.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/hostfile.c 30 Jun 2002 11:37:59 -0000 @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". * * - * Copyright (c) 1999,2000 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * Copyright (c) 1999 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,8 +36,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: hostfile.c,v 1.26 2001/04/12 19:15:24 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/hostfile.c,v 1.1.1.1.2.3 2001/09/28 01:33:34 green Exp $"); +RCSID("$OpenBSD: hostfile.c,v 1.29 2001/12/18 10:04:21 jakob Exp $"); #include "packet.h" #include "match.h" @@ -72,18 +71,7 @@ return 1; } -int -auth_rsa_read_key(char **cpp, u_int *bitsp, BIGNUM * e, BIGNUM * n) -{ - Key *k = key_new(KEY_RSA1); - int ret = hostfile_read_key(cpp, bitsp, k); - BN_copy(e, k->rsa->e); - BN_copy(n, k->rsa->n); - key_free(k); - return ret; -} - -int +static int hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum) { if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) Index: src/crypto/openssh/hostfile.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/hostfile.h,v retrieving revision 1.1.1.2.2.3 diff -u -u -r1.1.1.2.2.3 hostfile.h --- src/crypto/openssh/hostfile.h 28 Sep 2001 01:33:34 -0000 1.1.1.2.2.3 +++ src/crypto/openssh/hostfile.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.h,v 1.7 2001/02/08 19:30:51 itojun Exp $ */ +/* $OpenBSD: hostfile.h,v 1.10 2001/12/18 10:04:21 jakob Exp $ */ /* * Author: Tatu Ylonen @@ -14,27 +14,13 @@ #ifndef HOSTFILE_H #define HOSTFILE_H -int -auth_rsa_read_key(char **cpp, u_int *bitsp, BIGNUM * e, BIGNUM * n); - -/* - * 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; +int hostfile_read_key(char **, u_int *, Key *); HostStatus -check_host_in_hostfile(const char *filename, const char *host, Key *key, - Key *found, int *line); - -/* - * 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, Key *key); +check_host_in_hostfile(const char *, const char *, Key *, Key *, int *); +int add_host_to_hostfile(const char *, const char *, Key *); #endif Index: src/crypto/openssh/includes.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/includes.h,v retrieving revision 1.2.2.5 diff -u -u -r1.2.2.5 includes.h --- src/crypto/openssh/includes.h 28 Sep 2001 01:33:34 -0000 1.2.2.5 +++ src/crypto/openssh/includes.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,5 @@ -/* $OpenBSD: includes.h,v 1.14 2001/01/29 01:58:16 niklas Exp $ */ +/* $OpenBSD: includes.h,v 1.17 2002/01/26 16:44:22 stevesk Exp $ */ +/* $FreeBSD: src/crypto/openssh/includes.h,v 1.13 2002/06/29 11:22:20 des Exp $ */ /* * Author: Tatu Ylonen @@ -11,63 +12,150 @@ * 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". - * - * $FreeBSD: src/crypto/openssh/includes.h,v 1.2.2.5 2001/09/28 01:33:34 green Exp $ */ #ifndef INCLUDES_H #define INCLUDES_H -#define RCSID(msg) __RCSID(msg) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#define RCSID(msg) \ +__RCSID(msg) -#include -#include -#include -#include -#include -#include +#include "config.h" #include #include #include -#include +#include /* For O_NONBLOCK */ #include -#include #include #include #include #include #include -#include #include -#include #include -#include "version.h" - -/* Define this to be the path of the xauth program. */ -#ifndef XAUTH_PATH -#define XAUTH_PATH "/usr/X11R6/bin/xauth" +#ifdef HAVE_LIMITS_H +# include /* For PATH_MAX */ +#endif +#ifdef HAVE_GETOPT_H +# include +#endif +#ifdef HAVE_BSTRING_H +# include +#endif +#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \ + defined(GLOB_HAS_GL_MATCHC) +# include #endif +#ifdef HAVE_NETGROUP_H +# include +#endif +#if defined(HAVE_NETDB_H) +# include +#endif +#ifdef HAVE_ENDIAN_H +# include +#endif +#ifdef HAVE_TTYENT_H +# include +#endif +#ifdef HAVE_UTIME_H +# include +#endif +#ifdef HAVE_MAILLOCK_H +# include /* For _PATH_MAILDIR */ +#endif +#ifdef HAVE_NEXT +# include +#endif +#include /* For STDIN_FILENO, etc */ +#include /* Struct winsize */ /* - * Define this to use pipes instead of socketpairs for communicating with the - * client program. Socketpairs do not seem to work on all systems. - * Although pipes are bi-directional in FreeBSD, using pipes here will - * make uni-directional ! + *-*-nto-qnx needs these headers for strcasecmp and LASTLOG_FILE respectively */ -/* #define USE_PIPES 1 */ +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_LOGIN_H +# include +#endif + +#ifdef HAVE_UTMP_H +# include +#endif +#ifdef HAVE_UTMPX_H +# ifdef HAVE_TV_IN_UTMPX +# include +# endif +# include +#endif +#ifdef HAVE_LASTLOG_H +# include +#endif +#ifdef HAVE_PATHS_H +# include /* For _PATH_XXX */ +#endif + +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +# include /* For timersub */ +#endif +#include +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef HAVE_SYS_BSDTTY_H +# include +#endif +#include /* For MAXPATHLEN and roundup() */ +#ifdef HAVE_SYS_UN_H +# include /* For sockaddr_un */ +#endif +#ifdef HAVE_SYS_BITYPES_H +# include /* For u_intXX_t */ +#endif +#ifdef HAVE_SYS_CDEFS_H +# include /* For __P() */ +#endif +#ifdef HAVE_SYS_STAT_H +# include /* For S_* constants and macros */ +#endif +#ifdef HAVE_SYS_SYSMACROS_H +# include /* For MIN, MAX, etc */ +#endif +#ifdef HAVE_SYS_MMAN_H +#include /* for MAP_ANONYMOUS */ +#endif + +#include /* For typedefs */ +#include /* For IPv6 macros */ +#include /* For IPTOS macros */ +#include +#include +#ifdef HAVE_RPC_TYPES_H +# include /* For INADDR_LOOPBACK */ +#endif +#ifdef USE_PAM +# include +#endif +#ifdef HAVE_READPASSPHRASE_H +# include +#endif + +#include /* For OPENSSL_VERSION_NUMBER */ + +#include "defines.h" + +#include "version.h" +#include "openbsd-compat/openbsd-compat.h" +#include "openbsd-compat/bsd-cygwin_util.h" +#include "openbsd-compat/bsd-nextstep.h" + +#include "entropy.h" -#endif /* INCLUDES_H */ +#endif /* INCLUDES_H */ Index: src/crypto/openssh/install-sh =================================================================== RCS file: src/crypto/openssh/install-sh diff -N src/crypto/openssh/install-sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/install-sh 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# 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. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# 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}" + +transformbasename="" +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=: + chmodcmd="" + 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 Index: src/crypto/openssh/kex.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/kex.c,v retrieving revision 1.1.1.2.2.4 diff -u -u -r1.1.1.2.2.4 kex.c --- src/crypto/openssh/kex.c 28 Sep 2001 01:33:34 -0000 1.1.1.2.2.4 +++ src/crypto/openssh/kex.c 30 Jun 2002 11:37:59 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kex.c,v 1.33 2001/04/05 10:42:50 markus Exp $"); +RCSID("$OpenBSD: kex.c,v 1.51 2002/06/24 14:55:38 markus Exp $"); #include @@ -40,26 +40,32 @@ #include "mac.h" #include "match.h" #include "dispatch.h" +#include "monitor.h" #define KEX_COOKIE_LEN 16 -void kex_kexinit_finish(Kex *kex); -void kex_choose_conf(Kex *k); +/* Use privilege separation for sshd */ +int use_privsep; +struct monitor *pmonitor; + + +/* prototype */ +static void kex_kexinit_finish(Kex *); +static void kex_choose_conf(Kex *); /* put algorithm proposal into buffer */ -void +static void kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) { - u_int32_t rand = 0; int i; buffer_clear(b); - for (i = 0; i < KEX_COOKIE_LEN; i++) { - if (i % 4 == 0) - rand = arc4random(); - buffer_put_char(b, rand & 0xff); - rand >>= 8; - } + /* + * add a dummy cookie, the cookie will be overwritten by + * kex_send_kexinit(), each time a kexinit is set + */ + for (i = 0; i < KEX_COOKIE_LEN; i++) + buffer_put_char(b, 0); for (i = 0; i < PROPOSAL_MAX; i++) buffer_put_cstring(b, proposal[i]); buffer_put_char(b, 0); /* first_kex_packet_follows */ @@ -67,7 +73,7 @@ } /* parse buffer and return algorithm proposal */ -char ** +static char ** kex_buf2prop(Buffer *raw) { Buffer b; @@ -95,7 +101,7 @@ return proposal; } -void +static void kex_prop_free(char **proposal) { int i; @@ -105,28 +111,24 @@ xfree(proposal); } -void -kex_protocol_error(int type, int plen, void *ctxt) +static void +kex_protocol_error(int type, u_int32_t seq, void *ctxt) { - error("Hm, kex protocol error: type %d plen %d", type, plen); + error("Hm, kex protocol error: type %d seq %u", type, seq); } -void -kex_clear_dispatch(void) +static void +kex_reset_dispatch(void) { - int i; - - /* Numbers 30-49 are used for kex packets */ - for (i = 30; i <= 49; i++) - dispatch_set(i, &kex_protocol_error); + dispatch_range(SSH2_MSG_TRANSPORT_MIN, + SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); + dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); } void kex_finish(Kex *kex) { - int plen; - - kex_clear_dispatch(); + kex_reset_dispatch(); packet_start(SSH2_MSG_NEWKEYS); packet_send(); @@ -134,7 +136,8 @@ debug("SSH2_MSG_NEWKEYS sent"); debug("waiting for SSH2_MSG_NEWKEYS"); - packet_read_expect(&plen, SSH2_MSG_NEWKEYS); + packet_read_expect(SSH2_MSG_NEWKEYS); + packet_check_eom(); debug("SSH2_MSG_NEWKEYS received"); kex->done = 1; @@ -148,6 +151,10 @@ void kex_send_kexinit(Kex *kex) { + u_int32_t rand = 0; + u_char *cookie; + int i; + if (kex == NULL) { error("kex_send_kexinit: no kex, cannot rekey"); return; @@ -157,6 +164,17 @@ return; } kex->done = 0; + + /* generate a random cookie */ + if (buffer_len(&kex->my) < KEX_COOKIE_LEN) + fatal("kex_send_kexinit: kex proposal too short"); + cookie = buffer_ptr(&kex->my); + for (i = 0; i < KEX_COOKIE_LEN; i++) { + if (i % 4 == 0) + rand = arc4random(); + cookie[i] = rand; + rand >>= 8; + } packet_start(SSH2_MSG_KEXINIT); packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); packet_send(); @@ -165,7 +183,7 @@ } void -kex_input_kexinit(int type, int plen, void *ctxt) +kex_input_kexinit(int type, u_int32_t seq, void *ctxt) { char *ptr; int dlen; @@ -184,9 +202,9 @@ packet_get_char(); for (i = 0; i < PROPOSAL_MAX; i++) xfree(packet_get_string(NULL)); - packet_get_char(); - packet_get_int(); - packet_done(); + (void) packet_get_char(); + (void) packet_get_int(); + packet_check_eom(); kex_kexinit_finish(kex); } @@ -204,13 +222,12 @@ kex->done = 0; kex_send_kexinit(kex); /* we start */ - kex_clear_dispatch(); - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); + kex_reset_dispatch(); return kex; } -void +static void kex_kexinit_finish(Kex *kex) { if (!(kex->flags & KEX_INIT_SENT)) @@ -218,7 +235,7 @@ kex_choose_conf(kex); - switch(kex->kex_type) { + switch (kex->kex_type) { case DH_GRP1_SHA1: kexdh(kex); break; @@ -230,21 +247,22 @@ } } -void +static void choose_enc(Enc *enc, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) fatal("no matching cipher found: client %s server %s", client, server); - enc->cipher = cipher_by_name(name); - if (enc->cipher == NULL) + if ((enc->cipher = cipher_by_name(name)) == NULL) fatal("matching cipher is not supported: %s", name); enc->name = name; enc->enabled = 0; enc->iv = NULL; enc->key = NULL; + enc->key_len = cipher_keylen(enc->cipher); + enc->block_size = cipher_blocksize(enc->cipher); } -void +static void choose_mac(Mac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); @@ -259,7 +277,7 @@ mac->key = NULL; mac->enabled = 0; } -void +static void choose_comp(Comp *comp, char *client, char *server) { char *name = match_list(client, server, NULL); @@ -274,7 +292,7 @@ } comp->name = name; } -void +static void choose_kex(Kex *k, char *client, char *server) { k->name = match_list(client, server, NULL); @@ -287,7 +305,7 @@ } else fatal("bad kex alg %s", k->name); } -void +static void choose_hostkeyalg(Kex *k, char *client, char *server) { char *hostkeyalg = match_list(client, server, NULL); @@ -299,7 +317,7 @@ xfree(hostkeyalg); } -void +static void kex_choose_conf(Kex *kex) { Newkeys *newkeys; @@ -345,10 +363,10 @@ need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; - if (need < newkeys->enc.cipher->key_len) - need = newkeys->enc.cipher->key_len; - if (need < newkeys->enc.cipher->block_size) - need = newkeys->enc.cipher->block_size; + if (need < newkeys->enc.key_len) + need = newkeys->enc.key_len; + if (need < newkeys->enc.block_size) + need = newkeys->enc.block_size; if (need < newkeys->mac.key_len) need = newkeys->mac.key_len; } @@ -359,15 +377,15 @@ kex_prop_free(peer); } -u_char * +static u_char * derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) { Buffer b; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; char c = id; int have; - int mdsz = evp_md->md_size; + int mdsz = EVP_MD_size(evp_md); u_char *digest = xmalloc(roundup(need, mdsz)); buffer_init(&b); @@ -375,7 +393,8 @@ /* K1 = HASH(K || H || "A" || session_id) */ EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); + if (!(datafellows & SSH_BUG_DERIVEKEY)) + EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); EVP_DigestUpdate(&md, hash, mdsz); EVP_DigestUpdate(&md, &c, 1); EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); @@ -388,7 +407,8 @@ */ for (have = mdsz; need > have; have += mdsz) { EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); + if (!(datafellows & SSH_BUG_DERIVEKEY)) + EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); EVP_DigestUpdate(&md, hash, mdsz); EVP_DigestUpdate(&md, digest, have); EVP_DigestFinal(&md, digest + have, NULL); @@ -441,7 +461,7 @@ int i; fprintf(stderr, "%s\n", msg); - for (i = 0; i< len; i++){ + for (i = 0; i< len; i++) { fprintf(stderr, "%02x", digest[i]); if (i%32 == 31) fprintf(stderr, "\n"); Index: src/crypto/openssh/kex.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/kex.h,v retrieving revision 1.1.1.2.2.4 diff -u -u -r1.1.1.2.2.4 kex.h --- src/crypto/openssh/kex.h 28 Sep 2001 01:33:34 -0000 1.1.1.2.2.4 +++ src/crypto/openssh/kex.h 30 Jun 2002 11:37:59 -0000 @@ -1,7 +1,7 @@ -/* $OpenBSD: kex.h,v 1.22 2001/04/04 20:25:37 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.31 2002/05/16 22:02:50 markus Exp $ */ /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -71,13 +71,15 @@ char *name; Cipher *cipher; int enabled; + u_int key_len; + u_int block_size; u_char *key; u_char *iv; }; struct Mac { char *name; int enabled; - EVP_MD *md; + const EVP_MD *md; int mac_len; u_char *key; int key_len; @@ -107,24 +109,25 @@ int flags; char *client_version_string; char *server_version_string; - int (*check_host_key)(Key *hostkey); - Key *(*load_host_key)(int type); + int (*verify_host_key)(Key *); + Key *(*load_host_key)(int); + int (*host_key_index)(Key *); }; -Kex *kex_setup(char *proposal[PROPOSAL_MAX]); -void kex_finish(Kex *kex); +Kex *kex_setup(char *[PROPOSAL_MAX]); +void kex_finish(Kex *); -void kex_send_kexinit(Kex *kex); -void kex_input_kexinit(int type, int plen, void *ctxt); -void kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret); +void kex_send_kexinit(Kex *); +void kex_input_kexinit(int, u_int32_t, void *); +void kex_derive_keys(Kex *, u_char *, BIGNUM *); -void kexdh(Kex *); -void kexgex(Kex *); +void kexdh(Kex *); +void kexgex(Kex *); -Newkeys *kex_get_newkeys(int mode); +Newkeys *kex_get_newkeys(int); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) -void dump_digest(char *msg, u_char *digest, int len); +void dump_digest(char *, u_char *, int); #endif #endif Index: src/crypto/openssh/kexdh.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/kexdh.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 kexdh.c --- src/crypto/openssh/kexdh.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/kexdh.c 30 Jun 2002 11:37:59 -0000 @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kexdh.c,v 1.3 2001/04/04 09:48:34 markus Exp $"); +RCSID("$OpenBSD: kexdh.c,v 1.18 2002/03/18 17:50:31 provos Exp $"); #include #include @@ -37,26 +37,27 @@ #include "packet.h" #include "dh.h" #include "ssh2.h" +#include "monitor_wrap.h" -u_char * +static u_char * kex_dh_hash( char *client_version_string, char *server_version_string, char *ckexinit, int ckexinitlen, char *skexinit, int skexinitlen, - char *serverhostkeyblob, int sbloblen, + u_char *serverhostkeyblob, int sbloblen, BIGNUM *client_dh_pub, BIGNUM *server_dh_pub, BIGNUM *shared_secret) { Buffer b; static u_char digest[EVP_MAX_MD_SIZE]; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; buffer_init(&b); - buffer_put_string(&b, client_version_string, strlen(client_version_string)); - buffer_put_string(&b, server_version_string, strlen(server_version_string)); + buffer_put_cstring(&b, client_version_string); + buffer_put_cstring(&b, server_version_string); /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ buffer_put_int(&b, ckexinitlen+1); @@ -81,23 +82,22 @@ buffer_free(&b); #ifdef DEBUG_KEX - dump_digest("hash", digest, evp_md->md_size); + dump_digest("hash", digest, EVP_MD_size(evp_md)); #endif return digest; } /* client */ -void +static void kexdh_client(Kex *kex) { BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; DH *dh; Key *server_host_key; - char *server_host_key_blob = NULL, *signature = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf, *hash; u_int klen, kout, slen, sbloblen; - int dlen, plen; /* generate and send 'e', client DH public key */ dh = dh_new_group1(); @@ -115,23 +115,24 @@ #endif debug("expecting SSH2_MSG_KEXDH_REPLY"); - packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY); + packet_read_expect(SSH2_MSG_KEXDH_REPLY); /* key, cert */ server_host_key_blob = packet_get_string(&sbloblen); server_host_key = key_from_blob(server_host_key_blob, sbloblen); if (server_host_key == NULL) fatal("cannot decode server_host_key_blob"); - - if (kex->check_host_key == NULL) - fatal("cannot check server_host_key"); - kex->check_host_key(server_host_key); + if (server_host_key->type != kex->hostkey_type) + fatal("type mismatch for decoded server_host_key_blob"); + if (kex->verify_host_key == NULL) + fatal("cannot verify server_host_key"); + if (kex->verify_host_key(server_host_key) == -1) + fatal("server_host_key verification failed"); /* DH paramter f, server public DH key */ - dh_server_pub = BN_new(); - if (dh_server_pub == NULL) + if ((dh_server_pub = BN_new()) == NULL) fatal("dh_server_pub == NULL"); - packet_get_bignum2(dh_server_pub, &dlen); + packet_get_bignum2(dh_server_pub); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_server_pub= "); @@ -142,7 +143,7 @@ /* signed H */ signature = packet_get_string(&slen); - packet_done(); + packet_check_eom(); if (!dh_pub_is_valid(dh, dh_server_pub)) packet_disconnect("bad server public DH value"); @@ -153,7 +154,8 @@ #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - shared_secret = BN_new(); + if ((shared_secret = BN_new()) == NULL) + fatal("kexdh_client: BN_new failed"); BN_bin2bn(kbuf, kout, shared_secret); memset(kbuf, 0, klen); xfree(kbuf); @@ -170,10 +172,10 @@ shared_secret ); xfree(server_host_key_blob); - BN_free(dh_server_pub); + BN_clear_free(dh_server_pub); DH_free(dh); - if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1) + if (key_verify(server_host_key, signature, slen, hash, 20) != 1) fatal("key_verify failed for server_host_key"); key_free(server_host_key); xfree(signature); @@ -192,7 +194,7 @@ /* server */ -void +static void kexdh_server(Kex *kex) { BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; @@ -200,14 +202,14 @@ Key *server_host_key; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; u_int sbloblen, klen, kout; - int dlen, slen, plen; + u_int slen; /* generate server DH public key */ dh = dh_new_group1(); dh_gen_key(dh, kex->we_need * 8); debug("expecting SSH2_MSG_KEXDH_INIT"); - packet_read_expect(&plen, SSH2_MSG_KEXDH_INIT); + packet_read_expect(SSH2_MSG_KEXDH_INIT); if (kex->load_host_key == NULL) fatal("Cannot load hostkey"); @@ -216,10 +218,10 @@ fatal("Unsupported hostkey type %d", kex->hostkey_type); /* key, cert */ - dh_client_pub = BN_new(); - if (dh_client_pub == NULL) + if ((dh_client_pub = BN_new()) == NULL) fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub, &dlen); + packet_get_bignum2(dh_client_pub); + packet_check_eom(); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); @@ -243,7 +245,8 @@ #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - shared_secret = BN_new(); + if ((shared_secret = BN_new()) == NULL) + fatal("kexdh_server: BN_new failed"); BN_bin2bn(kbuf, kout, shared_secret); memset(kbuf, 0, klen); xfree(kbuf); @@ -256,12 +259,12 @@ kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), - (char *)server_host_key_blob, sbloblen, + server_host_key_blob, sbloblen, dh_client_pub, dh->pub_key, shared_secret ); - BN_free(dh_client_pub); + BN_clear_free(dh_client_pub); /* save session id := H */ /* XXX hashlen depends on KEX */ @@ -273,15 +276,15 @@ /* sign H */ /* XXX hashlen depends on KEX */ - key_sign(server_host_key, &signature, &slen, hash, 20); + PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20)); /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ packet_start(SSH2_MSG_KEXDH_REPLY); - packet_put_string((char *)server_host_key_blob, sbloblen); + packet_put_string(server_host_key_blob, sbloblen); packet_put_bignum2(dh->pub_key); /* f */ - packet_put_string((char *)signature, slen); + packet_put_string(signature, slen); packet_send(); xfree(signature); Index: src/crypto/openssh/kexgex.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/kexgex.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 kexgex.c --- src/crypto/openssh/kexgex.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/kexgex.c 30 Jun 2002 11:37:59 -0000 @@ -24,7 +24,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kexgex.c,v 1.5 2001/04/05 10:42:50 markus Exp $"); +RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $"); #include @@ -38,14 +38,15 @@ #include "dh.h" #include "ssh2.h" #include "compat.h" +#include "monitor_wrap.h" -u_char * +static u_char * kexgex_hash( char *client_version_string, char *server_version_string, char *ckexinit, int ckexinitlen, char *skexinit, int skexinitlen, - char *serverhostkeyblob, int sbloblen, + u_char *serverhostkeyblob, int sbloblen, int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen, BIGNUM *client_dh_pub, BIGNUM *server_dh_pub, @@ -53,12 +54,12 @@ { Buffer b; static u_char digest[EVP_MAX_MD_SIZE]; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; buffer_init(&b); - buffer_put_string(&b, client_version_string, strlen(client_version_string)); - buffer_put_string(&b, server_version_string, strlen(server_version_string)); + buffer_put_cstring(&b, client_version_string); + buffer_put_cstring(&b, server_version_string); /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ buffer_put_int(&b, ckexinitlen+1); @@ -92,14 +93,14 @@ buffer_free(&b); #ifdef DEBUG_KEXDH - dump_digest("hash", digest, evp_md->md_size); + dump_digest("hash", digest, EVP_MD_size(evp_md)); #endif return digest; } /* client */ -void +static void kexgex_client(Kex *kex) { BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; @@ -107,7 +108,7 @@ Key *server_host_key; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; u_int klen, kout, slen, sbloblen; - int dlen, plen, min, max, nbits; + int min, max, nbits; DH *dh; nbits = dh_estimate(kex->we_need * 8); @@ -138,15 +139,15 @@ packet_send(); debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); - packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP); + packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP); if ((p = BN_new()) == NULL) fatal("BN_new"); - packet_get_bignum2(p, &dlen); + packet_get_bignum2(p); if ((g = BN_new()) == NULL) fatal("BN_new"); - packet_get_bignum2(g, &dlen); - packet_done(); + packet_get_bignum2(g); + packet_check_eom(); if (BN_num_bits(p) < min || BN_num_bits(p) > max) fatal("DH_GEX group out of range: %d !< %d !< %d", @@ -169,23 +170,24 @@ packet_send(); debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); - packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY); + packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY); /* key, cert */ server_host_key_blob = packet_get_string(&sbloblen); server_host_key = key_from_blob(server_host_key_blob, sbloblen); if (server_host_key == NULL) fatal("cannot decode server_host_key_blob"); - - if (kex->check_host_key == NULL) - fatal("cannot check server_host_key"); - kex->check_host_key(server_host_key); + if (server_host_key->type != kex->hostkey_type) + fatal("type mismatch for decoded server_host_key_blob"); + if (kex->verify_host_key == NULL) + fatal("cannot verify server_host_key"); + if (kex->verify_host_key(server_host_key) == -1) + fatal("server_host_key verification failed"); /* DH paramter f, server public DH key */ - dh_server_pub = BN_new(); - if (dh_server_pub == NULL) + if ((dh_server_pub = BN_new()) == NULL) fatal("dh_server_pub == NULL"); - packet_get_bignum2(dh_server_pub, &dlen); + packet_get_bignum2(dh_server_pub); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_server_pub= "); @@ -196,7 +198,7 @@ /* signed H */ signature = packet_get_string(&slen); - packet_done(); + packet_check_eom(); if (!dh_pub_is_valid(dh, dh_server_pub)) packet_disconnect("bad server public DH value"); @@ -207,7 +209,8 @@ #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - shared_secret = BN_new(); + if ((shared_secret = BN_new()) == NULL) + fatal("kexgex_client: BN_new failed"); BN_bin2bn(kbuf, kout, shared_secret); memset(kbuf, 0, klen); xfree(kbuf); @@ -231,9 +234,9 @@ /* have keys, free DH */ DH_free(dh); xfree(server_host_key_blob); - BN_free(dh_server_pub); + BN_clear_free(dh_server_pub); - if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1) + if (key_verify(server_host_key, signature, slen, hash, 20) != 1) fatal("key_verify failed for server_host_key"); key_free(server_host_key); xfree(signature); @@ -252,15 +255,15 @@ /* server */ -void +static void kexgex_server(Kex *kex) { BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; Key *server_host_key; - DH *dh = dh; + DH *dh; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int sbloblen, klen, kout; - int min = -1, max = -1, nbits = -1, type, plen, dlen, slen; + u_int sbloblen, klen, kout, slen; + int min = -1, max = -1, nbits = -1, type; if (kex->load_host_key == NULL) fatal("Cannot load hostkey"); @@ -268,8 +271,8 @@ if (server_host_key == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); - type = packet_read(&plen); - switch(type){ + type = packet_read(); + switch (type) { case SSH2_MSG_KEX_DH_GEX_REQUEST: debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); min = packet_get_int(); @@ -288,13 +291,14 @@ default: fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); } - packet_done(); + packet_check_eom(); if (max < min || nbits < min || max < nbits) fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", min, nbits, max); - dh = choose_dh(min, nbits, max); + /* Contact privileged parent */ + dh = PRIVSEP(choose_dh(min, nbits, max)); if (dh == NULL) packet_disconnect("Protocol error: no matching DH grp found"); @@ -311,13 +315,13 @@ dh_gen_key(dh, kex->we_need * 8); debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); - packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_INIT); + packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT); /* key, cert */ - dh_client_pub = BN_new(); - if (dh_client_pub == NULL) + if ((dh_client_pub = BN_new()) == NULL) fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub, &dlen); + packet_get_bignum2(dh_client_pub); + packet_check_eom(); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); @@ -341,7 +345,8 @@ #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - shared_secret = BN_new(); + if ((shared_secret = BN_new()) == NULL) + fatal("kexgex_server: BN_new failed"); BN_bin2bn(kbuf, kout, shared_secret); memset(kbuf, 0, klen); xfree(kbuf); @@ -357,14 +362,14 @@ kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), - (char *)server_host_key_blob, sbloblen, + server_host_key_blob, sbloblen, min, nbits, max, dh->p, dh->g, dh_client_pub, dh->pub_key, shared_secret ); - BN_free(dh_client_pub); + BN_clear_free(dh_client_pub); /* save session id := H */ /* XXX hashlen depends on KEX */ @@ -376,17 +381,18 @@ /* sign H */ /* XXX hashlen depends on KEX */ - key_sign(server_host_key, &signature, &slen, hash, 20); + PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20)); /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); - packet_put_string((char *)server_host_key_blob, sbloblen); + packet_put_string(server_host_key_blob, sbloblen); packet_put_bignum2(dh->pub_key); /* f */ - packet_put_string((char *)signature, slen); + packet_put_string(signature, slen); packet_send(); + xfree(signature); xfree(server_host_key_blob); /* have keys, free DH */ Index: src/crypto/openssh/key.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/key.c,v retrieving revision 1.4.2.3 diff -u -u -r1.4.2.3 key.c --- src/crypto/openssh/key.c 28 Sep 2001 01:33:34 -0000 1.4.2.3 +++ src/crypto/openssh/key.c 30 Jun 2002 11:37:59 -0000 @@ -9,7 +9,7 @@ * called by a name other than "ssh" or "Secure Shell". * * - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,8 +32,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: key.c,v 1.25 2001/04/17 10:53:24 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/key.c,v 1.4.2.3 2001/09/28 01:33:34 green Exp $"); +RCSID("$OpenBSD: key.c,v 1.45 2002/06/23 03:26:19 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/key.c,v 1.12 2002/06/29 11:48:58 des Exp $"); #include @@ -55,22 +55,31 @@ DSA *dsa; k = xmalloc(sizeof(*k)); k->type = type; + k->flags = 0; k->dsa = NULL; k->rsa = NULL; switch (k->type) { case KEY_RSA1: case KEY_RSA: - rsa = RSA_new(); - rsa->n = BN_new(); - rsa->e = BN_new(); + if ((rsa = RSA_new()) == NULL) + fatal("key_new: RSA_new failed"); + if ((rsa->n = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((rsa->e = BN_new()) == NULL) + fatal("key_new: BN_new failed"); k->rsa = rsa; break; case KEY_DSA: - dsa = DSA_new(); - dsa->p = BN_new(); - dsa->q = BN_new(); - dsa->g = BN_new(); - dsa->pub_key = BN_new(); + if ((dsa = DSA_new()) == NULL) + fatal("key_new: DSA_new failed"); + if ((dsa->p = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->q = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->g = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->pub_key = BN_new()) == NULL) + fatal("key_new: BN_new failed"); k->dsa = dsa; break; case KEY_UNSPEC: @@ -81,6 +90,7 @@ } return k; } + Key * key_new_private(int type) { @@ -88,15 +98,22 @@ switch (k->type) { case KEY_RSA1: case KEY_RSA: - k->rsa->d = BN_new(); - k->rsa->iqmp = BN_new(); - k->rsa->q = BN_new(); - k->rsa->p = BN_new(); - k->rsa->dmq1 = BN_new(); - k->rsa->dmp1 = BN_new(); + if ((k->rsa->d = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->iqmp = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->q = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->p = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->dmq1 = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->dmp1 = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); break; case KEY_DSA: - k->dsa->priv_key = BN_new(); + if ((k->dsa->priv_key = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); break; case KEY_UNSPEC: break; @@ -105,6 +122,7 @@ } return k; } + void key_free(Key *k) { @@ -154,14 +172,14 @@ return 0; } -u_char* -key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) +static u_char* +key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) { - EVP_MD *md = NULL; + const EVP_MD *md = NULL; EVP_MD_CTX ctx; u_char *blob = NULL; u_char *retval = NULL; - int len = 0; + u_int len = 0; int nlen, elen; *dgst_raw_length = 0; @@ -201,8 +219,7 @@ retval = xmalloc(EVP_MAX_MD_SIZE); EVP_DigestInit(&ctx, md); EVP_DigestUpdate(&ctx, blob, len); - EVP_DigestFinal(&ctx, retval, NULL); - *dgst_raw_length = md->md_size; + EVP_DigestFinal(&ctx, retval, dgst_raw_length); memset(blob, 0, len); xfree(blob); } else { @@ -211,15 +228,15 @@ return retval; } -char* -key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) +static char* +key_fingerprint_hex(u_char* dgst_raw, u_int dgst_raw_len) { char *retval; int i; retval = xmalloc(dgst_raw_len * 3 + 1); retval[0] = '\0'; - for(i = 0; i < dgst_raw_len; i++) { + for (i = 0; i < dgst_raw_len; i++) { char hex[4]; snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); strlcat(retval, hex, dgst_raw_len * 3); @@ -228,8 +245,8 @@ return retval; } -char* -key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len) +static char* +key_fingerprint_bubblebabble(u_char* dgst_raw, u_int dgst_raw_len) { char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', @@ -280,12 +297,12 @@ { char *retval = NULL; u_char *dgst_raw; - size_t dgst_raw_len; - + u_int dgst_raw_len; + dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); if (!dgst_raw) fatal("key_fingerprint: null from key_fingerprint_raw()"); - switch(dgst_rep) { + switch (dgst_rep) { case SSH_FP_HEX: retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); break; @@ -309,7 +326,7 @@ * last processed (and maybe modified) character. Note that this may modify * the buffer containing the number. */ -int +static int read_bignum(char **cpp, BIGNUM * value) { char *cp = *cpp; @@ -345,7 +362,8 @@ *cpp = cp; return 1; } -int + +static int write_bignum(FILE *f, BIGNUM *num) { char *buf = BN_bn2dec(num); @@ -354,11 +372,11 @@ return 0; } fprintf(f, " %s", buf); - xfree(buf); + OPENSSL_free(buf); return 1; } -/* returns 1 ok, -1 error, 0 type mismatch */ +/* returns 1 ok, -1 error */ int key_read(Key *ret, char **cpp) { @@ -371,7 +389,7 @@ cp = *cpp; - switch(ret->type) { + switch (ret->type) { case KEY_RSA1: /* Get number of bits. */ if (*cp < '0' || *cp > '9') @@ -413,21 +431,22 @@ } else if (ret->type != type) { /* is a key, but different type */ debug3("key_read: type mismatch"); - return 0; + return -1; } len = 2*strlen(cp); blob = xmalloc(len); n = uudecode(cp, blob, len); if (n < 0) { error("key_read: uudecode %s failed", cp); + xfree(blob); return -1; } k = key_from_blob(blob, n); + xfree(blob); if (k == NULL) { error("key_read: key_from_blob %s failed", cp); return -1; } - xfree(blob); if (k->type != type) { error("key_read: type mismatch: encoding error"); key_free(k); @@ -454,9 +473,9 @@ #endif } /*XXXX*/ + key_free(k); if (success != 1) break; - key_free(k); /* advance cp: skip whitespace and data */ while (*cp == ' ' || *cp == '\t') cp++; @@ -470,11 +489,13 @@ } return success; } + int key_write(Key *key, FILE *f) { - int success = 0; - u_int bits = 0; + int n, success = 0; + u_int len, bits = 0; + u_char *blob, *uu; if (key->type == KEY_RSA1 && key->rsa != NULL) { /* size of modulus 'n' */ @@ -488,8 +509,6 @@ } } else if ((key->type == KEY_DSA && key->dsa != NULL) || (key->type == KEY_RSA && key->rsa != NULL)) { - int len, n; - u_char *blob, *uu; key_to_blob(key, &blob, &len); uu = xmalloc(2*len); n = uuencode(blob, len, uu, 2*len); @@ -502,6 +521,7 @@ } return success; } + char * key_type(Key *k) { @@ -518,6 +538,7 @@ } return "unknown"; } + char * key_ssh_name(Key *k) { @@ -531,8 +552,10 @@ } return "ssh-unknown"; } + u_int -key_size(Key *k){ +key_size(Key *k) +{ switch (k->type) { case KEY_RSA1: case KEY_RSA: @@ -545,7 +568,7 @@ return 0; } -RSA * +static RSA * rsa_generate_private_key(u_int bits) { RSA *private; @@ -555,7 +578,7 @@ return private; } -DSA* +static DSA* dsa_generate_private_key(u_int bits) { DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); @@ -615,15 +638,15 @@ int key_type_from_name(char *name) { - if (strcmp(name, "rsa1") == 0){ + if (strcmp(name, "rsa1") == 0) { return KEY_RSA1; - } else if (strcmp(name, "rsa") == 0){ + } else if (strcmp(name, "rsa") == 0) { return KEY_RSA; - } else if (strcmp(name, "dsa") == 0){ + } else if (strcmp(name, "dsa") == 0) { return KEY_DSA; - } else if (strcmp(name, "ssh-rsa") == 0){ + } else if (strcmp(name, "ssh-rsa") == 0) { return KEY_RSA; - } else if (strcmp(name, "ssh-dss") == 0){ + } else if (strcmp(name, "ssh-dss") == 0) { return KEY_DSA; } debug2("key_type_from_name: unknown key type '%s'", name); @@ -639,7 +662,7 @@ return 0; s = cp = xstrdup(names); for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { + (p = strsep(&cp, ","))) { switch (key_type_from_name(p)) { case KEY_RSA1: case KEY_UNSPEC: @@ -653,7 +676,7 @@ } Key * -key_from_blob(char *blob, int blen) +key_from_blob(u_char *blob, int blen) { Buffer b; char *ktype; @@ -668,7 +691,7 @@ ktype = buffer_get_string(&b, NULL); type = key_type_from_name(ktype); - switch(type){ + switch (type) { case KEY_RSA: key = key_new(type); buffer_get_bignum2(&b, key->rsa->e); @@ -714,7 +737,7 @@ return 0; } buffer_init(&b); - switch(key->type){ + switch (key->type) { case KEY_DSA: buffer_put_cstring(&b, key_ssh_name(key)); buffer_put_bignum2(&b, key->dsa->p); @@ -728,8 +751,9 @@ buffer_put_bignum2(&b, key->rsa->n); break; default: - error("key_to_blob: illegal key type %d", key->type); - break; + error("key_to_blob: unsupported key type %d", key->type); + buffer_free(&b); + return 0; } len = buffer_len(&b); buf = xmalloc(len); @@ -746,10 +770,10 @@ int key_sign( Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen) + u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { - switch(key->type){ + switch (key->type) { case KEY_DSA: return ssh_dss_sign(key, sigp, lenp, data, datalen); break; @@ -763,13 +787,20 @@ } } +/* + * key_verify returns 1 for a correct signature, 0 for an incorrect signature + * and -1 on error. + */ int key_verify( Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen) + u_char *signature, u_int signaturelen, + u_char *data, u_int datalen) { - switch(key->type){ + if (signaturelen == 0) + return -1; + + switch (key->type) { case KEY_DSA: return ssh_dss_verify(key, signature, signaturelen, data, datalen); break; @@ -781,4 +812,46 @@ return -1; break; } +} + +/* Converts a private to a public key */ +Key * +key_demote(Key *k) +{ + Key *pk; + + pk = xmalloc(sizeof(*pk)); + pk->type = k->type; + pk->flags = k->flags; + pk->dsa = NULL; + pk->rsa = NULL; + + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + if ((pk->rsa = RSA_new()) == NULL) + fatal("key_demote: RSA_new failed"); + if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) + fatal("key_demote: BN_dup failed"); + break; + case KEY_DSA: + if ((pk->dsa = DSA_new()) == NULL) + fatal("key_demote: DSA_new failed"); + if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) + fatal("key_demote: BN_dup failed"); + break; + default: + fatal("key_free: bad key type %d", k->type); + break; + } + + return (pk); } Index: src/crypto/openssh/key.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/key.h,v retrieving revision 1.1.1.2.2.3 diff -u -u -r1.1.1.2.2.3 key.h --- src/crypto/openssh/key.h 28 Sep 2001 01:33:34 -0000 1.1.1.2.2.3 +++ src/crypto/openssh/key.h 30 Jun 2002 11:37:59 -0000 @@ -1,7 +1,7 @@ -/* $OpenBSD: key.h,v 1.12 2001/04/17 10:53:24 markus Exp $ */ +/* $OpenBSD: key.h,v 1.19 2002/03/18 17:23:31 markus Exp $ */ /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,41 +44,38 @@ SSH_FP_HEX, SSH_FP_BUBBLEBABBLE }; + +/* key is stored in external hardware */ +#define KEY_FLAG_EXT 0x0001 + struct Key { - int type; + int type; + int flags; RSA *rsa; DSA *dsa; }; -Key *key_new(int type); -Key *key_new_private(int type); -void key_free(Key *k); -int key_equal(Key *a, Key *b); -char *key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep); -char *key_type(Key *k); -int key_write(Key *key, FILE *f); -int key_read(Key *key, char **cpp); -u_int key_size(Key *k); - -Key *key_generate(int type, u_int bits); -Key *key_from_private(Key *k); -int key_type_from_name(char *name); - -Key *key_from_blob(char *blob, int blen); -int key_to_blob(Key *key, u_char **blobp, u_int *lenp); -char *key_ssh_name(Key *k); -int key_names_valid2(const char *names); - -int -key_sign( - Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen); - -int -key_verify( - Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen); +Key *key_new(int); +Key *key_new_private(int); +void key_free(Key *); +Key *key_demote(Key *); +int key_equal(Key *, Key *); +char *key_fingerprint(Key *, enum fp_type, enum fp_rep); +char *key_type(Key *); +int key_write(Key *, FILE *); +int key_read(Key *, char **); +u_int key_size(Key *); + +Key *key_generate(int, u_int); +Key *key_from_private(Key *); +int key_type_from_name(char *); + +Key *key_from_blob(u_char *, int); +int key_to_blob(Key *, u_char **, u_int *); +char *key_ssh_name(Key *); +int key_names_valid2(const char *); + +int key_sign(Key *, u_char **, u_int *, u_char *, u_int); +int key_verify(Key *, u_char *, u_int, u_char *, u_int); #endif Index: src/crypto/openssh/log.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/log.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 log.c --- src/crypto/openssh/log.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/log.c 30 Jun 2002 11:37:59 -0000 @@ -34,7 +34,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: log.c,v 1.17 2001/03/04 17:42:28 millert Exp $"); +RCSID("$OpenBSD: log.c,v 1.22 2002/02/22 12:20:34 markus Exp $"); #include "log.h" #include "xmalloc.h" @@ -57,6 +57,9 @@ { "DAEMON", SYSLOG_FACILITY_DAEMON }, { "USER", SYSLOG_FACILITY_USER }, { "AUTH", SYSLOG_FACILITY_AUTH }, +#ifdef LOG_AUTHPRIV + { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, +#endif { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, @@ -65,7 +68,7 @@ { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, - { NULL, 0 } + { NULL, SYSLOG_FACILITY_NOT_SET } }; static struct { @@ -82,7 +85,7 @@ { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, - { NULL, 0 } + { NULL, SYSLOG_LEVEL_NOT_SET } }; SyslogFacility @@ -93,7 +96,7 @@ for (i = 0; log_facilities[i].name; i++) if (strcasecmp(log_facilities[i].name, name) == 0) return log_facilities[i].val; - return (SyslogFacility) - 1; + return SYSLOG_FACILITY_NOT_SET; } LogLevel @@ -104,18 +107,7 @@ for (i = 0; log_levels[i].name; i++) if (strcasecmp(log_levels[i].name, name) == 0) return log_levels[i].val; - return (LogLevel) - 1; -} -/* Fatal messages. This function never returns. */ - -void -fatal(const char *fmt,...) -{ - va_list args; - va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); - va_end(args); - fatal_cleanup(); + return SYSLOG_LEVEL_NOT_SET; } /* Error messages that should be logged. */ @@ -237,7 +229,7 @@ for (cu = fatal_cleanups; cu; cu = next_cu) { next_cu = cu->next; debug("Calling cleanup 0x%lx(0x%lx)", - (u_long) cu->proc, (u_long) cu->context); + (u_long) cu->proc, (u_long) cu->context); (*cu->proc) (cu->context); } exit(255); @@ -284,6 +276,11 @@ case SYSLOG_FACILITY_AUTH: log_facility = LOG_AUTH; break; +#ifdef LOG_AUTHPRIV + case SYSLOG_FACILITY_AUTHPRIV: + log_facility = LOG_AUTHPRIV; + break; +#endif case SYSLOG_FACILITY_LOCAL0: log_facility = LOG_LOCAL0; break; Index: src/crypto/openssh/log.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/log.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 log.h --- src/crypto/openssh/log.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/log.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.2 2001/01/29 01:58:16 niklas Exp $ */ +/* $OpenBSD: log.h,v 1.7 2002/05/19 20:54:52 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -15,11 +15,16 @@ #ifndef SSH_LOG_H #define SSH_LOG_H +#include /* Needed for LOG_AUTHPRIV (if present) */ + /* Supported syslog facilities and levels. */ typedef enum { SYSLOG_FACILITY_DAEMON, SYSLOG_FACILITY_USER, SYSLOG_FACILITY_AUTH, +#ifdef LOG_AUTHPRIV + SYSLOG_FACILITY_AUTHPRIV, +#endif SYSLOG_FACILITY_LOCAL0, SYSLOG_FACILITY_LOCAL1, SYSLOG_FACILITY_LOCAL2, @@ -27,7 +32,8 @@ SYSLOG_FACILITY_LOCAL4, SYSLOG_FACILITY_LOCAL5, SYSLOG_FACILITY_LOCAL6, - SYSLOG_FACILITY_LOCAL7 + SYSLOG_FACILITY_LOCAL7, + SYSLOG_FACILITY_NOT_SET = -1 } SyslogFacility; typedef enum { @@ -38,38 +44,27 @@ SYSLOG_LEVEL_VERBOSE, SYSLOG_LEVEL_DEBUG1, SYSLOG_LEVEL_DEBUG2, - SYSLOG_LEVEL_DEBUG3 + SYSLOG_LEVEL_DEBUG3, + SYSLOG_LEVEL_NOT_SET = -1 } LogLevel; -/* Initializes logging. */ -void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr); - -/* Logging implementation, depending on server or client */ -void do_log(LogLevel level, const char *fmt, va_list args); -/* name to facility/level */ -SyslogFacility log_facility_number(char *name); -LogLevel log_level_number(char *name); - -/* Output a message to syslog or stderr */ -void fatal(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void error(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void log(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void verbose(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void debug2(const char *fmt,...) __attribute__((format(printf, 1, 2))); -void debug3(const char *fmt,...) __attribute__((format(printf, 1, 2))); +void log_init(char *, LogLevel, SyslogFacility, int); -/* same as fatal() but w/o logging */ -void fatal_cleanup(void); +SyslogFacility log_facility_number(char *); +LogLevel log_level_number(char *); -/* - * Registers a cleanup function to be called by fatal()/fatal_cleanup() - * 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); +void fatal(const char *, ...) __attribute__((format(printf, 1, 2))); +void error(const char *, ...) __attribute__((format(printf, 1, 2))); +void log(const char *, ...) __attribute__((format(printf, 1, 2))); +void verbose(const char *, ...) __attribute__((format(printf, 1, 2))); +void debug(const char *, ...) __attribute__((format(printf, 1, 2))); +void debug2(const char *, ...) __attribute__((format(printf, 1, 2))); +void debug3(const char *, ...) __attribute__((format(printf, 1, 2))); + +void fatal_cleanup(void); +void fatal_add_cleanup(void (*) (void *), void *); +void fatal_remove_cleanup(void (*) (void *), void *); -/* Removes a cleanup function to be called at fatal(). */ -void fatal_remove_cleanup(void (*proc) (void *context), void *context); +void do_log(LogLevel, const char *, va_list); #endif Index: src/crypto/openssh/loginrec.c =================================================================== RCS file: src/crypto/openssh/loginrec.c diff -N src/crypto/openssh/loginrec.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/loginrec.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,1510 @@ +/* + * Copyright (c) 2000 Andre Lucas. All rights reserved. + * Portions copyright (c) 1998 Todd C. Miller + * Portions copyright (c) 1996 Jason Downs + * Portions copyright (c) 1996 Theo de Raadt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + ** loginrec.c: platform-independent login recording and lastlog retrieval + **/ + +/* + The new login code explained + ============================ + + This code attempts to provide a common interface to login recording + (utmp and friends) and last login time retrieval. + + Its primary means of achieving this is to use 'struct logininfo', a + union of all the useful fields in the various different types of + system login record structures one finds on UNIX variants. + + We depend on autoconf to define which recording methods are to be + used, and which fields are contained in the relevant data structures + on the local system. Many C preprocessor symbols affect which code + gets compiled here. + + The code is designed to make it easy to modify a particular + recording method, without affecting other methods nor requiring so + many nested conditional compilation blocks as were commonplace in + the old code. + + For login recording, we try to use the local system's libraries as + these are clearly most likely to work correctly. For utmp systems + this usually means login() and logout() or setutent() etc., probably + in libutil, along with logwtmp() etc. On these systems, we fall back + to writing the files directly if we have to, though this method + requires very thorough testing so we do not corrupt local auditing + information. These files and their access methods are very system + specific indeed. + + For utmpx systems, the corresponding library functions are + setutxent() etc. To the author's knowledge, all utmpx systems have + these library functions and so no direct write is attempted. If such + a system exists and needs support, direct analogues of the [uw]tmp + code should suffice. + + Retrieving the time of last login ('lastlog') is in some ways even + more problemmatic than login recording. Some systems provide a + simple table of all users which we seek based on uid and retrieve a + relatively standard structure. Others record the same information in + a directory with a separate file, and others don't record the + information separately at all. For systems in the latter category, + we look backwards in the wtmp or wtmpx file for the last login entry + for our user. Naturally this is slower and on busy systems could + incur a significant performance penalty. + + Calling the new code + -------------------- + + In OpenSSH all login recording and retrieval is performed in + login.c. Here you'll find working examples. Also, in the logintest.c + program there are more examples. + + Internal handler calling method + ------------------------------- + + When a call is made to login_login() or login_logout(), both + routines set a struct logininfo flag defining which action (log in, + or log out) is to be taken. They both then call login_write(), which + calls whichever of the many structure-specific handlers autoconf + selects for the local system. + + The handlers themselves handle system data structure specifics. Both + struct utmp and struct utmpx have utility functions (see + construct_utmp*()) to try to make it simpler to add extra systems + that introduce new features to either structure. + + While it may seem terribly wasteful to replicate so much similar + code for each method, experience has shown that maintaining code to + write both struct utmp and utmpx in one function, whilst maintaining + support for all systems whether they have library support or not, is + a difficult and time-consuming task. + + Lastlog support proceeds similarly. Functions login_get_lastlog() + (and its OpenSSH-tuned friend login_get_lastlog_time()) call + getlast_entry(), which tries one of three methods to find the last + login time. It uses local system lastlog support if it can, + otherwise it tries wtmp or wtmpx before giving up and returning 0, + meaning "tilt". + + Maintenance + ----------- + + In many cases it's possible to tweak autoconf to select the correct + methods for a particular platform, either by improving the detection + code (best), or by presetting DISABLE_ or CONF__FILE + symbols for the platform. + + Use logintest to check which symbols are defined before modifying + configure.ac and loginrec.c. (You have to build logintest yourself + with 'make logintest' as it's not built by default.) + + Otherwise, patches to the specific method(s) are very helpful! + +*/ + +/** + ** TODO: + ** homegrown ttyslot() + ** test, test, test + ** + ** Platform status: + ** ---------------- + ** + ** Known good: + ** Linux (Redhat 6.2, Debian) + ** Solaris + ** HP-UX 10.20 (gcc only) + ** IRIX + ** NeXT - M68k/HPPA/Sparc (4.2/3.3) + ** + ** Testing required: Please send reports! + ** NetBSD + ** HP-UX 11 + ** AIX + ** + ** Platforms with known problems: + ** Some variants of Slackware Linux + ** + **/ + +#include "includes.h" + +#include "ssh.h" +#include "xmalloc.h" +#include "loginrec.h" +#include "log.h" +#include "atomicio.h" + +RCSID("$Id$"); + +#ifdef HAVE_UTIL_H +# include +#endif + +#ifdef HAVE_LIBUTIL_H +# include +#endif + +/** + ** prototypes for helper functions in this file + **/ + +#if HAVE_UTMP_H +void set_utmp_time(struct logininfo *li, struct utmp *ut); +void construct_utmp(struct logininfo *li, struct utmp *ut); +#endif + +#ifdef HAVE_UTMPX_H +void set_utmpx_time(struct logininfo *li, struct utmpx *ut); +void construct_utmpx(struct logininfo *li, struct utmpx *ut); +#endif + +int utmp_write_entry(struct logininfo *li); +int utmpx_write_entry(struct logininfo *li); +int wtmp_write_entry(struct logininfo *li); +int wtmpx_write_entry(struct logininfo *li); +int lastlog_write_entry(struct logininfo *li); +int syslogin_write_entry(struct logininfo *li); + +int getlast_entry(struct logininfo *li); +int lastlog_get_entry(struct logininfo *li); +int wtmp_get_entry(struct logininfo *li); +int wtmpx_get_entry(struct logininfo *li); + +/* pick the shortest string */ +#define MIN_SIZEOF(s1,s2) ( sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2) ) + +/** + ** platform-independent login functions + **/ + +/* login_login(struct logininfo *) -Record a login + * + * Call with a pointer to a struct logininfo initialised with + * login_init_entry() or login_alloc_entry() + * + * Returns: + * >0 if successful + * 0 on failure (will use OpenSSH's logging facilities for diagnostics) + */ +int +login_login (struct logininfo *li) +{ + li->type = LTYPE_LOGIN; + return login_write(li); +} + + +/* login_logout(struct logininfo *) - Record a logout + * + * Call as with login_login() + * + * Returns: + * >0 if successful + * 0 on failure (will use OpenSSH's logging facilities for diagnostics) + */ +int +login_logout(struct logininfo *li) +{ + li->type = LTYPE_LOGOUT; + return login_write(li); +} + +/* login_get_lastlog_time(int) - Retrieve the last login time + * + * Retrieve the last login time for the given uid. Will try to use the + * system lastlog facilities if they are available, but will fall back + * to looking in wtmp/wtmpx if necessary + * + * Returns: + * 0 on failure, or if user has never logged in + * Time in seconds from the epoch if successful + * + * Useful preprocessor symbols: + * DISABLE_LASTLOG: If set, *never* even try to retrieve lastlog + * info + * USE_LASTLOG: If set, indicates the presence of system lastlog + * facilities. If this and DISABLE_LASTLOG are not set, + * try to retrieve lastlog information from wtmp/wtmpx. + */ +unsigned int +login_get_lastlog_time(const int uid) +{ + struct logininfo li; + + if (login_get_lastlog(&li, uid)) + return li.tv_sec; + else + return 0; +} + +/* login_get_lastlog(struct logininfo *, int) - Retrieve a lastlog entry + * + * Retrieve a logininfo structure populated (only partially) with + * information from the system lastlog data, or from wtmp/wtmpx if no + * system lastlog information exists. + * + * Note this routine must be given a pre-allocated logininfo. + * + * Returns: + * >0: A pointer to your struct logininfo if successful + * 0 on failure (will use OpenSSH's logging facilities for diagnostics) + * + */ +struct logininfo * +login_get_lastlog(struct logininfo *li, const int uid) +{ + struct passwd *pw; + + memset(li, '\0', sizeof(*li)); + li->uid = uid; + + /* + * If we don't have a 'real' lastlog, we need the username to + * reliably search wtmp(x) for the last login (see + * wtmp_get_entry().) + */ + pw = getpwuid(uid); + if (pw == NULL) + fatal("login_get_lastlog: Cannot find account for uid %i", uid); + + /* No MIN_SIZEOF here - we absolutely *must not* truncate the + * username */ + strlcpy(li->username, pw->pw_name, sizeof(li->username)); + + if (getlast_entry(li)) + return li; + else + return NULL; +} + + +/* login_alloc_entry(int, char*, char*, char*) - Allocate and initialise + * a logininfo structure + * + * This function creates a new struct logininfo, a data structure + * meant to carry the information required to portably record login info. + * + * Returns a pointer to a newly created struct logininfo. If memory + * allocation fails, the program halts. + */ +struct +logininfo *login_alloc_entry(int pid, const char *username, + const char *hostname, const char *line) +{ + struct logininfo *newli; + + newli = (struct logininfo *) xmalloc (sizeof(*newli)); + (void)login_init_entry(newli, pid, username, hostname, line); + return newli; +} + + +/* login_free_entry(struct logininfo *) - free struct memory */ +void +login_free_entry(struct logininfo *li) +{ + xfree(li); +} + + +/* login_init_entry(struct logininfo *, int, char*, char*, char*) + * - initialise a struct logininfo + * + * Populates a new struct logininfo, a data structure meant to carry + * the information required to portably record login info. + * + * Returns: 1 + */ +int +login_init_entry(struct logininfo *li, int pid, const char *username, + const char *hostname, const char *line) +{ + struct passwd *pw; + + memset(li, 0, sizeof(*li)); + + li->pid = pid; + + /* set the line information */ + if (line) + line_fullname(li->line, line, sizeof(li->line)); + + if (username) { + strlcpy(li->username, username, sizeof(li->username)); + pw = getpwnam(li->username); + if (pw == NULL) + fatal("login_init_entry: Cannot find user \"%s\"", li->username); + li->uid = pw->pw_uid; + } + + if (hostname) + strlcpy(li->hostname, hostname, sizeof(li->hostname)); + + return 1; +} + +/* login_set_current_time(struct logininfo *) - set the current time + * + * Set the current time in a logininfo structure. This function is + * meant to eliminate the need to deal with system dependencies for + * time handling. + */ +void +login_set_current_time(struct logininfo *li) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + li->tv_sec = tv.tv_sec; + li->tv_usec = tv.tv_usec; +} + +/* copy a sockaddr_* into our logininfo */ +void +login_set_addr(struct logininfo *li, const struct sockaddr *sa, + const unsigned int sa_size) +{ + unsigned int bufsize = sa_size; + + /* make sure we don't overrun our union */ + if (sizeof(li->hostaddr) < sa_size) + bufsize = sizeof(li->hostaddr); + + memcpy((void *)&(li->hostaddr.sa), (const void *)sa, bufsize); +} + + +/** + ** login_write: Call low-level recording functions based on autoconf + ** results + **/ +int +login_write (struct logininfo *li) +{ +#ifndef HAVE_CYGWIN + if ((int)geteuid() != 0) { + log("Attempt to write login records by non-root user (aborting)"); + return 1; + } +#endif + + /* set the timestamp */ + login_set_current_time(li); +#ifdef USE_LOGIN + syslogin_write_entry(li); +#endif +#ifdef USE_LASTLOG + if (li->type == LTYPE_LOGIN) { + lastlog_write_entry(li); + } +#endif +#ifdef USE_UTMP + utmp_write_entry(li); +#endif +#ifdef USE_WTMP + wtmp_write_entry(li); +#endif +#ifdef USE_UTMPX + utmpx_write_entry(li); +#endif +#ifdef USE_WTMPX + wtmpx_write_entry(li); +#endif + return 0; +} + +#ifdef LOGIN_NEEDS_UTMPX +int +login_utmp_only(struct logininfo *li) +{ + li->type = LTYPE_LOGIN; + login_set_current_time(li); +# ifdef USE_UTMP + utmp_write_entry(li); +# endif +# ifdef USE_WTMP + wtmp_write_entry(li); +# endif +# ifdef USE_UTMPX + utmpx_write_entry(li); +# endif +# ifdef USE_WTMPX + wtmpx_write_entry(li); +# endif + return 0; +} +#endif + +/** + ** getlast_entry: Call low-level functions to retrieve the last login + ** time. + **/ + +/* take the uid in li and return the last login time */ +int +getlast_entry(struct logininfo *li) +{ +#ifdef USE_LASTLOG + return(lastlog_get_entry(li)); +#else /* !USE_LASTLOG */ + +#ifdef DISABLE_LASTLOG + /* On some systems we shouldn't even try to obtain last login + * time, e.g. AIX */ + return 0; +# else /* DISABLE_LASTLOG */ + /* Try to retrieve the last login time from wtmp */ +# if defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) + /* retrieve last login time from utmp */ + return (wtmp_get_entry(li)); +# else /* defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) */ + /* If wtmp isn't available, try wtmpx */ +# if defined(USE_WTMPX) && (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX)) + /* retrieve last login time from utmpx */ + return (wtmpx_get_entry(li)); +# else + /* Give up: No means of retrieving last login time */ + return 0; +# endif /* USE_WTMPX && (HAVE_TIME_IN_UTMPX || HAVE_TV_IN_UTMPX) */ +# endif /* USE_WTMP && (HAVE_TIME_IN_UTMP || HAVE_TV_IN_UTMP) */ +# endif /* DISABLE_LASTLOG */ +#endif /* USE_LASTLOG */ +} + + + +/* + * 'line' string utility functions + * + * These functions process the 'line' string into one of three forms: + * + * 1. The full filename (including '/dev') + * 2. The stripped name (excluding '/dev') + * 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00 + * /dev/pts/1 -> ts/1 ) + * + * Form 3 is used on some systems to identify a .tmp.? entry when + * attempting to remove it. Typically both addition and removal is + * performed by one application - say, sshd - so as long as the choice + * uniquely identifies a terminal it's ok. + */ + + +/* line_fullname(): add the leading '/dev/' if it doesn't exist make + * sure dst has enough space, if not just copy src (ugh) */ +char * +line_fullname(char *dst, const char *src, int dstsize) +{ + memset(dst, '\0', dstsize); + if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5))) { + strlcpy(dst, src, dstsize); + } else { + strlcpy(dst, "/dev/", dstsize); + strlcat(dst, src, dstsize); + } + return dst; +} + +/* line_stripname(): strip the leading '/dev' if it exists, return dst */ +char * +line_stripname(char *dst, const char *src, int dstsize) +{ + memset(dst, '\0', dstsize); + if (strncmp(src, "/dev/", 5) == 0) + strlcpy(dst, src + 5, dstsize); + else + strlcpy(dst, src, dstsize); + return dst; +} + +/* line_abbrevname(): Return the abbreviated (usually four-character) + * form of the line (Just use the last characters of the + * full name.) + * + * NOTE: use strncpy because we do NOT necessarily want zero + * termination */ +char * +line_abbrevname(char *dst, const char *src, int dstsize) +{ + size_t len; + + memset(dst, '\0', dstsize); + + /* Always skip prefix if present */ + if (strncmp(src, "/dev/", 5) == 0) + src += 5; + +#ifdef WITH_ABBREV_NO_TTY + if (strncmp(src, "tty", 3) == 0) + src += 3; +#endif + + len = strlen(src); + + if (len > 0) { + if (((int)len - dstsize) > 0) + src += ((int)len - dstsize); + + /* note: _don't_ change this to strlcpy */ + strncpy(dst, src, (size_t)dstsize); + } + + return dst; +} + +/** + ** utmp utility functions + ** + ** These functions manipulate struct utmp, taking system differences + ** into account. + **/ + +#if defined(USE_UTMP) || defined (USE_WTMP) || defined (USE_LOGIN) + +/* build the utmp structure */ +void +set_utmp_time(struct logininfo *li, struct utmp *ut) +{ +# ifdef HAVE_TV_IN_UTMP + ut->ut_tv.tv_sec = li->tv_sec; + ut->ut_tv.tv_usec = li->tv_usec; +# else +# ifdef HAVE_TIME_IN_UTMP + ut->ut_time = li->tv_sec; +# endif +# endif +} + +void +construct_utmp(struct logininfo *li, + struct utmp *ut) +{ + memset(ut, '\0', sizeof(*ut)); + + /* First fill out fields used for both logins and logouts */ + +# ifdef HAVE_ID_IN_UTMP + line_abbrevname(ut->ut_id, li->line, sizeof(ut->ut_id)); +# endif + +# ifdef HAVE_TYPE_IN_UTMP + /* This is done here to keep utmp constants out of struct logininfo */ + switch (li->type) { + case LTYPE_LOGIN: + ut->ut_type = USER_PROCESS; +#ifdef _CRAY + cray_set_tmpdir(ut); +#endif + break; + case LTYPE_LOGOUT: + ut->ut_type = DEAD_PROCESS; +#ifdef _CRAY + cray_retain_utmp(ut, li->pid); +#endif + break; + } +# endif + set_utmp_time(li, ut); + + line_stripname(ut->ut_line, li->line, sizeof(ut->ut_line)); + +# ifdef HAVE_PID_IN_UTMP + ut->ut_pid = li->pid; +# endif + + /* If we're logging out, leave all other fields blank */ + if (li->type == LTYPE_LOGOUT) + return; + + /* + * These fields are only used when logging in, and are blank + * for logouts. + */ + + /* Use strncpy because we don't necessarily want null termination */ + strncpy(ut->ut_name, li->username, MIN_SIZEOF(ut->ut_name, li->username)); +# ifdef HAVE_HOST_IN_UTMP + strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname)); +# endif +# ifdef HAVE_ADDR_IN_UTMP + /* this is just a 32-bit IP address */ + if (li->hostaddr.sa.sa_family == AF_INET) + ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; +# endif +} +#endif /* USE_UTMP || USE_WTMP || USE_LOGIN */ + +/** + ** utmpx utility functions + ** + ** These functions manipulate struct utmpx, accounting for system + ** variations. + **/ + +#if defined(USE_UTMPX) || defined (USE_WTMPX) +/* build the utmpx structure */ +void +set_utmpx_time(struct logininfo *li, struct utmpx *utx) +{ +# ifdef HAVE_TV_IN_UTMPX + utx->ut_tv.tv_sec = li->tv_sec; + utx->ut_tv.tv_usec = li->tv_usec; +# else /* HAVE_TV_IN_UTMPX */ +# ifdef HAVE_TIME_IN_UTMPX + utx->ut_time = li->tv_sec; +# endif /* HAVE_TIME_IN_UTMPX */ +# endif /* HAVE_TV_IN_UTMPX */ +} + +void +construct_utmpx(struct logininfo *li, struct utmpx *utx) +{ + memset(utx, '\0', sizeof(*utx)); +# ifdef HAVE_ID_IN_UTMPX + line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id)); +# endif + + /* this is done here to keep utmp constants out of loginrec.h */ + switch (li->type) { + case LTYPE_LOGIN: + utx->ut_type = USER_PROCESS; + break; + case LTYPE_LOGOUT: + utx->ut_type = DEAD_PROCESS; + break; + } + line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line)); + set_utmpx_time(li, utx); + utx->ut_pid = li->pid; + /* strncpy(): Don't necessarily want null termination */ + strncpy(utx->ut_name, li->username, MIN_SIZEOF(utx->ut_name, li->username)); + + if (li->type == LTYPE_LOGOUT) + return; + + /* + * These fields are only used when logging in, and are blank + * for logouts. + */ + +# ifdef HAVE_HOST_IN_UTMPX + strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); +# endif +# ifdef HAVE_ADDR_IN_UTMPX + /* this is just a 32-bit IP address */ + if (li->hostaddr.sa.sa_family == AF_INET) + utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr; +# endif +# ifdef HAVE_SYSLEN_IN_UTMPX + /* ut_syslen is the length of the utx_host string */ + utx->ut_syslen = MIN(strlen(li->hostname), sizeof(utx->ut_host)); +# endif +} +#endif /* USE_UTMPX || USE_WTMPX */ + +/** + ** Low-level utmp functions + **/ + +/* FIXME: (ATL) utmp_write_direct needs testing */ +#ifdef USE_UTMP + +/* if we can, use pututline() etc. */ +# if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \ + defined(HAVE_PUTUTLINE) +# define UTMP_USE_LIBRARY +# endif + + +/* write a utmp entry with the system's help (pututline() and pals) */ +# ifdef UTMP_USE_LIBRARY +static int +utmp_write_library(struct logininfo *li, struct utmp *ut) +{ + setutent(); + pututline(ut); + +# ifdef HAVE_ENDUTENT + endutent(); +# endif + return 1; +} +# else /* UTMP_USE_LIBRARY */ + +/* write a utmp entry direct to the file */ +/* This is a slightly modification of code in OpenBSD's login.c */ +static int +utmp_write_direct(struct logininfo *li, struct utmp *ut) +{ + struct utmp old_ut; + register int fd; + int tty; + + /* FIXME: (ATL) ttyslot() needs local implementation */ + +#if defined(HAVE_GETTTYENT) + register struct ttyent *ty; + + tty=0; + + setttyent(); + while ((struct ttyent *)0 != (ty = getttyent())) { + tty++; + if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line))) + break; + } + endttyent(); + + if((struct ttyent *)0 == ty) { + log("utmp_write_entry: tty not found"); + return(1); + } +#else /* FIXME */ + + tty = ttyslot(); /* seems only to work for /dev/ttyp? style names */ + +#endif /* HAVE_GETTTYENT */ + + if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) { + (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); + /* + * Prevent luser from zero'ing out ut_host. + * If the new ut_line is empty but the old one is not + * and ut_line and ut_name match, preserve the old ut_line. + */ + if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) && + (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') && + (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) && + (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0)) { + (void)memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); + } + + (void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET); + if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) + log("utmp_write_direct: error writing %s: %s", + UTMP_FILE, strerror(errno)); + + (void)close(fd); + return 1; + } else { + return 0; + } +} +# endif /* UTMP_USE_LIBRARY */ + +static int +utmp_perform_login(struct logininfo *li) +{ + struct utmp ut; + + construct_utmp(li, &ut); +# ifdef UTMP_USE_LIBRARY + if (!utmp_write_library(li, &ut)) { + log("utmp_perform_login: utmp_write_library() failed"); + return 0; + } +# else + if (!utmp_write_direct(li, &ut)) { + log("utmp_perform_login: utmp_write_direct() failed"); + return 0; + } +# endif + return 1; +} + + +static int +utmp_perform_logout(struct logininfo *li) +{ + struct utmp ut; + + construct_utmp(li, &ut); +# ifdef UTMP_USE_LIBRARY + if (!utmp_write_library(li, &ut)) { + log("utmp_perform_logout: utmp_write_library() failed"); + return 0; + } +# else + if (!utmp_write_direct(li, &ut)) { + log("utmp_perform_logout: utmp_write_direct() failed"); + return 0; + } +# endif + return 1; +} + + +int +utmp_write_entry(struct logininfo *li) +{ + switch(li->type) { + case LTYPE_LOGIN: + return utmp_perform_login(li); + + case LTYPE_LOGOUT: + return utmp_perform_logout(li); + + default: + log("utmp_write_entry: invalid type field"); + return 0; + } +} +#endif /* USE_UTMP */ + + +/** + ** Low-level utmpx functions + **/ + +/* not much point if we don't want utmpx entries */ +#ifdef USE_UTMPX + +/* if we have the wherewithall, use pututxline etc. */ +# if !defined(DISABLE_PUTUTXLINE) && defined(HAVE_SETUTXENT) && \ + defined(HAVE_PUTUTXLINE) +# define UTMPX_USE_LIBRARY +# endif + + +/* write a utmpx entry with the system's help (pututxline() and pals) */ +# ifdef UTMPX_USE_LIBRARY +static int +utmpx_write_library(struct logininfo *li, struct utmpx *utx) +{ + setutxent(); + pututxline(utx); + +# ifdef HAVE_ENDUTXENT + endutxent(); +# endif + return 1; +} + +# else /* UTMPX_USE_LIBRARY */ + +/* write a utmp entry direct to the file */ +static int +utmpx_write_direct(struct logininfo *li, struct utmpx *utx) +{ + log("utmpx_write_direct: not implemented!"); + return 0; +} +# endif /* UTMPX_USE_LIBRARY */ + +static int +utmpx_perform_login(struct logininfo *li) +{ + struct utmpx utx; + + construct_utmpx(li, &utx); +# ifdef UTMPX_USE_LIBRARY + if (!utmpx_write_library(li, &utx)) { + log("utmpx_perform_login: utmp_write_library() failed"); + return 0; + } +# else + if (!utmpx_write_direct(li, &ut)) { + log("utmpx_perform_login: utmp_write_direct() failed"); + return 0; + } +# endif + return 1; +} + + +static int +utmpx_perform_logout(struct logininfo *li) +{ + struct utmpx utx; + + construct_utmpx(li, &utx); +# ifdef HAVE_ID_IN_UTMPX + line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id)); +# endif +# ifdef HAVE_TYPE_IN_UTMPX + utx.ut_type = DEAD_PROCESS; +# endif + +# ifdef UTMPX_USE_LIBRARY + utmpx_write_library(li, &utx); +# else + utmpx_write_direct(li, &utx); +# endif + return 1; +} + +int +utmpx_write_entry(struct logininfo *li) +{ + switch(li->type) { + case LTYPE_LOGIN: + return utmpx_perform_login(li); + case LTYPE_LOGOUT: + return utmpx_perform_logout(li); + default: + log("utmpx_write_entry: invalid type field"); + return 0; + } +} +#endif /* USE_UTMPX */ + + +/** + ** Low-level wtmp functions + **/ + +#ifdef USE_WTMP + +/* write a wtmp entry direct to the end of the file */ +/* This is a slight modification of code in OpenBSD's logwtmp.c */ +static int +wtmp_write(struct logininfo *li, struct utmp *ut) +{ + struct stat buf; + int fd, ret = 1; + + if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { + log("wtmp_write: problem writing %s: %s", + WTMP_FILE, strerror(errno)); + return 0; + } + if (fstat(fd, &buf) == 0) + if (atomicio(write, fd, ut, sizeof(*ut)) != sizeof(*ut)) { + ftruncate(fd, buf.st_size); + log("wtmp_write: problem writing %s: %s", + WTMP_FILE, strerror(errno)); + ret = 0; + } + (void)close(fd); + return ret; +} + +static int +wtmp_perform_login(struct logininfo *li) +{ + struct utmp ut; + + construct_utmp(li, &ut); + return wtmp_write(li, &ut); +} + + +static int +wtmp_perform_logout(struct logininfo *li) +{ + struct utmp ut; + + construct_utmp(li, &ut); + return wtmp_write(li, &ut); +} + + +int +wtmp_write_entry(struct logininfo *li) +{ + switch(li->type) { + case LTYPE_LOGIN: + return wtmp_perform_login(li); + case LTYPE_LOGOUT: + return wtmp_perform_logout(li); + default: + log("wtmp_write_entry: invalid type field"); + return 0; + } +} + + +/* Notes on fetching login data from wtmp/wtmpx + * + * Logouts are usually recorded with (amongst other things) a blank + * username on a given tty line. However, some systems (HP-UX is one) + * leave all fields set, but change the ut_type field to DEAD_PROCESS. + * + * Since we're only looking for logins here, we know that the username + * must be set correctly. On systems that leave it in, we check for + * ut_type==USER_PROCESS (indicating a login.) + * + * Portability: Some systems may set something other than USER_PROCESS + * to indicate a login process. I don't know of any as I write. Also, + * it's possible that some systems may both leave the username in + * place and not have ut_type. + */ + +/* return true if this wtmp entry indicates a login */ +static int +wtmp_islogin(struct logininfo *li, struct utmp *ut) +{ + if (strncmp(li->username, ut->ut_name, + MIN_SIZEOF(li->username, ut->ut_name)) == 0) { +# ifdef HAVE_TYPE_IN_UTMP + if (ut->ut_type & USER_PROCESS) + return 1; +# else + return 1; +# endif + } + return 0; +} + +int +wtmp_get_entry(struct logininfo *li) +{ + struct stat st; + struct utmp ut; + int fd, found=0; + + /* Clear the time entries in our logininfo */ + li->tv_sec = li->tv_usec = 0; + + if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { + log("wtmp_get_entry: problem opening %s: %s", + WTMP_FILE, strerror(errno)); + return 0; + } + if (fstat(fd, &st) != 0) { + log("wtmp_get_entry: couldn't stat %s: %s", + WTMP_FILE, strerror(errno)); + close(fd); + return 0; + } + + /* Seek to the start of the last struct utmp */ + if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) { + /* Looks like we've got a fresh wtmp file */ + close(fd); + return 0; + } + + while (!found) { + if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) { + log("wtmp_get_entry: read of %s failed: %s", + WTMP_FILE, strerror(errno)); + close (fd); + return 0; + } + if ( wtmp_islogin(li, &ut) ) { + found = 1; + /* We've already checked for a time in struct + * utmp, in login_getlast(). */ +# ifdef HAVE_TIME_IN_UTMP + li->tv_sec = ut.ut_time; +# else +# if HAVE_TV_IN_UTMP + li->tv_sec = ut.ut_tv.tv_sec; +# endif +# endif + line_fullname(li->line, ut.ut_line, + MIN_SIZEOF(li->line, ut.ut_line)); +# ifdef HAVE_HOST_IN_UTMP + strlcpy(li->hostname, ut.ut_host, + MIN_SIZEOF(li->hostname, ut.ut_host)); +# endif + continue; + } + /* Seek back 2 x struct utmp */ + if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) { + /* We've found the start of the file, so quit */ + close (fd); + return 0; + } + } + + /* We found an entry. Tidy up and return */ + close(fd); + return 1; +} +# endif /* USE_WTMP */ + + +/** + ** Low-level wtmpx functions + **/ + +#ifdef USE_WTMPX +/* write a wtmpx entry direct to the end of the file */ +/* This is a slight modification of code in OpenBSD's logwtmp.c */ +static int +wtmpx_write(struct logininfo *li, struct utmpx *utx) +{ + struct stat buf; + int fd, ret = 1; + + if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { + log("wtmpx_write: problem opening %s: %s", + WTMPX_FILE, strerror(errno)); + return 0; + } + + if (fstat(fd, &buf) == 0) + if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) { + ftruncate(fd, buf.st_size); + log("wtmpx_write: problem writing %s: %s", + WTMPX_FILE, strerror(errno)); + ret = 0; + } + (void)close(fd); + + return ret; +} + + +static int +wtmpx_perform_login(struct logininfo *li) +{ + struct utmpx utx; + + construct_utmpx(li, &utx); + return wtmpx_write(li, &utx); +} + + +static int +wtmpx_perform_logout(struct logininfo *li) +{ + struct utmpx utx; + + construct_utmpx(li, &utx); + return wtmpx_write(li, &utx); +} + + +int +wtmpx_write_entry(struct logininfo *li) +{ + switch(li->type) { + case LTYPE_LOGIN: + return wtmpx_perform_login(li); + case LTYPE_LOGOUT: + return wtmpx_perform_logout(li); + default: + log("wtmpx_write_entry: invalid type field"); + return 0; + } +} + +/* Please see the notes above wtmp_islogin() for information about the + next two functions */ + +/* Return true if this wtmpx entry indicates a login */ +static int +wtmpx_islogin(struct logininfo *li, struct utmpx *utx) +{ + if ( strncmp(li->username, utx->ut_name, + MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) { +# ifdef HAVE_TYPE_IN_UTMPX + if (utx->ut_type == USER_PROCESS) + return 1; +# else + return 1; +# endif + } + return 0; +} + + +int +wtmpx_get_entry(struct logininfo *li) +{ + struct stat st; + struct utmpx utx; + int fd, found=0; + + /* Clear the time entries */ + li->tv_sec = li->tv_usec = 0; + + if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { + log("wtmpx_get_entry: problem opening %s: %s", + WTMPX_FILE, strerror(errno)); + return 0; + } + if (fstat(fd, &st) != 0) { + log("wtmpx_get_entry: couldn't stat %s: %s", + WTMP_FILE, strerror(errno)); + close(fd); + return 0; + } + + /* Seek to the start of the last struct utmpx */ + if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) { + /* probably a newly rotated wtmpx file */ + close(fd); + return 0; + } + + while (!found) { + if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) { + log("wtmpx_get_entry: read of %s failed: %s", + WTMPX_FILE, strerror(errno)); + close (fd); + return 0; + } + /* Logouts are recorded as a blank username on a particular line. + * So, we just need to find the username in struct utmpx */ + if ( wtmpx_islogin(li, &utx) ) { +# ifdef HAVE_TV_IN_UTMPX + li->tv_sec = utx.ut_tv.tv_sec; +# else +# ifdef HAVE_TIME_IN_UTMPX + li->tv_sec = utx.ut_time; +# endif +# endif + line_fullname(li->line, utx.ut_line, sizeof(li->line)); +# ifdef HAVE_HOST_IN_UTMPX + strlcpy(li->hostname, utx.ut_host, + MIN_SIZEOF(li->hostname, utx.ut_host)); +# endif + continue; + } + if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) { + close (fd); + return 0; + } + } + + close(fd); + return 1; +} +#endif /* USE_WTMPX */ + +/** + ** Low-level libutil login() functions + **/ + +#ifdef USE_LOGIN +static int +syslogin_perform_login(struct logininfo *li) +{ + struct utmp *ut; + + if (! (ut = (struct utmp *)malloc(sizeof(*ut)))) { + log("syslogin_perform_login: couldn't malloc()"); + return 0; + } + construct_utmp(li, ut); + login(ut); + + return 1; +} + +static int +syslogin_perform_logout(struct logininfo *li) +{ +# ifdef HAVE_LOGOUT + char line[8]; + + (void)line_stripname(line, li->line, sizeof(line)); + + if (!logout(line)) { + log("syslogin_perform_logout: logout() returned an error"); +# ifdef HAVE_LOGWTMP + } else { + logwtmp(line, "", ""); +# endif + } + /* FIXME: (ATL - if the need arises) What to do if we have + * login, but no logout? what if logout but no logwtmp? All + * routines are in libutil so they should all be there, + * but... */ +# endif + return 1; +} + +int +syslogin_write_entry(struct logininfo *li) +{ + switch (li->type) { + case LTYPE_LOGIN: + return syslogin_perform_login(li); + case LTYPE_LOGOUT: + return syslogin_perform_logout(li); + default: + log("syslogin_write_entry: Invalid type field"); + return 0; + } +} +#endif /* USE_LOGIN */ + +/* end of file log-syslogin.c */ + +/** + ** Low-level lastlog functions + **/ + +#ifdef USE_LASTLOG +#define LL_FILE 1 +#define LL_DIR 2 +#define LL_OTHER 3 + +static void +lastlog_construct(struct logininfo *li, struct lastlog *last) +{ + /* clear the structure */ + memset(last, '\0', sizeof(*last)); + + (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); + strlcpy(last->ll_host, li->hostname, + MIN_SIZEOF(last->ll_host, li->hostname)); + last->ll_time = li->tv_sec; +} + +static int +lastlog_filetype(char *filename) +{ + struct stat st; + + if (stat(LASTLOG_FILE, &st) != 0) { + log("lastlog_perform_login: Couldn't stat %s: %s", LASTLOG_FILE, + strerror(errno)); + return 0; + } + if (S_ISDIR(st.st_mode)) + return LL_DIR; + else if (S_ISREG(st.st_mode)) + return LL_FILE; + else + return LL_OTHER; +} + + +/* open the file (using filemode) and seek to the login entry */ +static int +lastlog_openseek(struct logininfo *li, int *fd, int filemode) +{ + off_t offset; + int type; + char lastlog_file[1024]; + + type = lastlog_filetype(LASTLOG_FILE); + switch (type) { + case LL_FILE: + strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); + break; + case LL_DIR: + snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", + LASTLOG_FILE, li->username); + break; + default: + log("lastlog_openseek: %.100s is not a file or directory!", + LASTLOG_FILE); + return 0; + } + + *fd = open(lastlog_file, filemode); + if ( *fd < 0) { + debug("lastlog_openseek: Couldn't open %s: %s", + lastlog_file, strerror(errno)); + return 0; + } + + if (type == LL_FILE) { + /* find this uid's offset in the lastlog file */ + offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); + + if ( lseek(*fd, offset, SEEK_SET) != offset ) { + log("lastlog_openseek: %s->lseek(): %s", + lastlog_file, strerror(errno)); + return 0; + } + } + + return 1; +} + +static int +lastlog_perform_login(struct logininfo *li) +{ + struct lastlog last; + int fd; + + /* create our struct lastlog */ + lastlog_construct(li, &last); + + if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) + return(0); + + /* write the entry */ + if (atomicio(write, fd, &last, sizeof(last)) != sizeof(last)) { + close(fd); + log("lastlog_write_filemode: Error writing to %s: %s", + LASTLOG_FILE, strerror(errno)); + return 0; + } + + close(fd); + return 1; +} + +int +lastlog_write_entry(struct logininfo *li) +{ + switch(li->type) { + case LTYPE_LOGIN: + return lastlog_perform_login(li); + default: + log("lastlog_write_entry: Invalid type field"); + return 0; + } +} + +static void +lastlog_populate_entry(struct logininfo *li, struct lastlog *last) +{ + line_fullname(li->line, last->ll_line, sizeof(li->line)); + strlcpy(li->hostname, last->ll_host, + MIN_SIZEOF(li->hostname, last->ll_host)); + li->tv_sec = last->ll_time; +} + +int +lastlog_get_entry(struct logininfo *li) +{ + struct lastlog last; + int fd; + + if (!lastlog_openseek(li, &fd, O_RDONLY)) + return 0; + + if (atomicio(read, fd, &last, sizeof(last)) != sizeof(last)) { + close(fd); + log("lastlog_get_entry: Error reading from %s: %s", + LASTLOG_FILE, strerror(errno)); + return 0; + } + + close(fd); + + lastlog_populate_entry(li, &last); + + return 1; +} +#endif /* USE_LASTLOG */ Index: src/crypto/openssh/loginrec.h =================================================================== RCS file: src/crypto/openssh/loginrec.h diff -N src/crypto/openssh/loginrec.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/loginrec.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,140 @@ +#ifndef _HAVE_LOGINREC_H_ +#define _HAVE_LOGINREC_H_ + +/* + * Copyright (c) 2000 Andre Lucas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + ** loginrec.h: platform-independent login recording and lastlog retrieval + **/ + +#include "includes.h" + +#include +#include +#include + +/* RCSID("$Id$"); */ + +/** + ** you should use the login_* calls to work around platform dependencies + **/ + +/* + * login_netinfo structure + */ + +union login_netinfo { + struct sockaddr sa; + struct sockaddr_in sa_in; + struct sockaddr_storage sa_storage; +}; + +/* + * * logininfo structure * + */ +/* types - different to utmp.h 'type' macros */ +/* (though set to the same value as linux, openbsd and others...) */ +#define LTYPE_LOGIN 7 +#define LTYPE_LOGOUT 8 + +/* string lengths - set very long */ +#define LINFO_PROGSIZE 64 +#define LINFO_LINESIZE 64 +#define LINFO_NAMESIZE 64 +#define LINFO_HOSTSIZE 256 + +struct logininfo { + char progname[LINFO_PROGSIZE]; /* name of program (for PAM) */ + int progname_null; + short int type; /* type of login (LTYPE_*) */ + int pid; /* PID of login process */ + int uid; /* UID of this user */ + char line[LINFO_LINESIZE]; /* tty/pty name */ + char username[LINFO_NAMESIZE]; /* login username */ + char hostname[LINFO_HOSTSIZE]; /* remote hostname */ + /* 'exit_status' structure components */ + int exit; /* process exit status */ + int termination; /* process termination status */ + /* struct timeval (sys/time.h) isn't always available, if it isn't we'll + * use time_t's value as tv_sec and set tv_usec to 0 + */ + unsigned int tv_sec; + unsigned int tv_usec; + union login_netinfo hostaddr; /* caller's host address(es) */ +}; /* struct logininfo */ + +/* + * login recording functions + */ + +/** 'public' functions */ + +/* construct a new login entry */ +struct logininfo *login_alloc_entry(int pid, const char *username, + const char *hostname, const char *line); +/* free a structure */ +void login_free_entry(struct logininfo *li); +/* fill out a pre-allocated structure with useful information */ +int login_init_entry(struct logininfo *li, int pid, const char *username, + const char *hostname, const char *line); +/* place the current time in a logininfo struct */ +void login_set_current_time(struct logininfo *li); + +/* record the entry */ +int login_login (struct logininfo *li); +int login_logout(struct logininfo *li); +#ifdef LOGIN_NEEDS_UTMPX +int login_utmp_only(struct logininfo *li); +#endif + +/** End of public functions */ + +/* record the entry */ +int login_write (struct logininfo *li); +int login_log_entry(struct logininfo *li); + +/* set the network address based on network address type */ +void login_set_addr(struct logininfo *li, const struct sockaddr *sa, + const unsigned int sa_size); + +/* + * lastlog retrieval functions + */ +/* lastlog *entry* functions fill out a logininfo */ +struct logininfo *login_get_lastlog(struct logininfo *li, const int uid); +/* lastlog *time* functions return time_t equivalent (uint) */ +unsigned int login_get_lastlog_time(const int uid); + +/* produce various forms of the line filename */ +char *line_fullname(char *dst, const char *src, int dstsize); +char *line_stripname(char *dst, const char *src, int dstsize); +char *line_abbrevname(char *dst, const char *src, int dstsize); + +#endif /* _HAVE_LOGINREC_H_ */ Index: src/crypto/openssh/logintest.c =================================================================== RCS file: src/crypto/openssh/logintest.c diff -N src/crypto/openssh/logintest.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/logintest.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2000 Andre Lucas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Markus Friedl. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + ** logintest.c: simple test driver for platform-independent login recording + ** and lastlog retrieval + **/ + +#include "includes.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif + +#include "loginrec.h" + +RCSID("$Id$"); + +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif + +#define PAUSE_BEFORE_LOGOUT 3 + +int nologtest = 0; +int compile_opts_only = 0; +int be_verbose = 0; + + +/* Dump a logininfo to stdout. Assumes a tab size of 8 chars. */ +void +dump_logininfo(struct logininfo *li, char *descname) +{ + /* yes I know how nasty this is */ + printf("struct logininfo %s = {\n\t" + "progname\t'%s'\n\ttype\t\t%d\n\t" + "pid\t\t%d\n\tuid\t\t%d\n\t" + "line\t\t'%s'\n\tusername\t'%s'\n\t" + "hostname\t'%s'\n\texit\t\t%d\n\ttermination\t%d\n\t" + "tv_sec\t%d\n\ttv_usec\t%d\n\t" + "struct login_netinfo hostaddr {\n\t\t" + "struct sockaddr sa {\n" + "\t\t\tfamily\t%d\n\t\t}\n" + "\t}\n" + "}\n", + descname, li->progname, li->type, + li->pid, li->uid, li->line, + li->username, li->hostname, li->exit, + li->termination, li->tv_sec, li->tv_usec, + li->hostaddr.sa.sa_family); +} + + +int +testAPI() +{ + struct logininfo *li1; + struct passwd *pw; + struct hostent *he; + struct sockaddr_in sa_in4; + char cmdstring[256], stripline[8]; + char username[32]; +#ifdef HAVE_TIME_H + time_t t0, t1, t2, logintime, logouttime; + char s_t0[64],s_t1[64],s_t2[64]; + char s_logintime[64], s_logouttime[64]; /* ctime() strings */ +#endif + + printf("**\n** Testing the API...\n**\n"); + + pw = getpwuid(getuid()); + strlcpy(username, pw->pw_name, sizeof(username)); + + /* gethostname(hostname, sizeof(hostname)); */ + + printf("login_alloc_entry test (no host info):\n"); + + /* FIXME fake tty more effectively - this could upset some platforms */ + li1 = login_alloc_entry((int)getpid(), username, NULL, ttyname(0)); + strlcpy(li1->progname, "OpenSSH-logintest", sizeof(li1->progname)); + + if (be_verbose) + dump_logininfo(li1, "li1"); + + printf("Setting host address info for 'localhost' (may call out):\n"); + if (! (he = gethostbyname("localhost"))) { + printf("Couldn't set hostname(lookup failed)\n"); + } else { + /* NOTE: this is messy, but typically a program wouldn't have to set + * any of this, a sockaddr_in* would be already prepared */ + memcpy((void *)&(sa_in4.sin_addr), (void *)&(he->h_addr_list[0][0]), + sizeof(struct in_addr)); + login_set_addr(li1, (struct sockaddr *) &sa_in4, sizeof(sa_in4)); + strlcpy(li1->hostname, "localhost", sizeof(li1->hostname)); + } + if (be_verbose) + dump_logininfo(li1, "li1"); + + if ((int)geteuid() != 0) { + printf("NOT RUNNING LOGIN TESTS - you are not root!\n"); + return 1; + } + + if (nologtest) + return 1; + + line_stripname(stripline, li1->line, sizeof(stripline)); + + printf("Performing an invalid login attempt (no type field)\n--\n"); + login_write(li1); + printf("--\n(Should have written errors to stderr)\n"); + +#ifdef HAVE_TIME_H + (void)time(&t0); + strlcpy(s_t0, ctime(&t0), sizeof(s_t0)); + t1 = login_get_lastlog_time(getuid()); + strlcpy(s_t1, ctime(&t1), sizeof(s_t1)); + printf("Before logging in:\n\tcurrent time is %d - %s\t" + "lastlog time is %d - %s\n", + (int)t0, s_t0, (int)t1, s_t1); +#endif + + printf("Performing a login on line %s ", stripline); +#ifdef HAVE_TIME_H + (void)time(&logintime); + strlcpy(s_logintime, ctime(&logintime), sizeof(s_logintime)); + printf("at %d - %s", (int)logintime, s_logintime); +#endif + printf("--\n"); + login_login(li1); + + snprintf(cmdstring, sizeof(cmdstring), "who | grep '%s '", + stripline); + system(cmdstring); + + printf("--\nPausing for %d second(s)...\n", PAUSE_BEFORE_LOGOUT); + sleep(PAUSE_BEFORE_LOGOUT); + + printf("Performing a logout "); +#ifdef HAVE_TIME_H + (void)time(&logouttime); + strlcpy(s_logouttime, ctime(&logouttime), sizeof(s_logouttime)); + printf("at %d - %s", (int)logouttime, s_logouttime); +#endif + printf("\nThe root login shown above should be gone.\n" + "If the root login hasn't gone, but another user on the same\n" + "pty has, this is OK - we're hacking it here, and there\n" + "shouldn't be two users on one pty in reality...\n" + "-- ('who' output follows)\n"); + login_logout(li1); + + system(cmdstring); + printf("-- ('who' output ends)\n"); + +#ifdef HAVE_TIME_H + t2 = login_get_lastlog_time(getuid()); + strlcpy(s_t2, ctime(&t2), sizeof(s_t2)); + printf("After logging in, lastlog time is %d - %s\n", (int)t2, s_t2); + if (t1 == t2) + printf("The lastlog times before and after logging in are the " + "same.\nThis indicates that lastlog is ** NOT WORKING " + "CORRECTLY **\n"); + else if (t0 != t2) + /* We can be off by a second or so, even when recording works fine. + * I'm not 100% sure why, but it's true. */ + printf("** The login time and the lastlog time differ.\n" + "** This indicates that lastlog is either recording the " + "wrong time,\n** or retrieving the wrong entry.\n" + "If it's off by less than %d second(s) " + "run the test again.\n", PAUSE_BEFORE_LOGOUT); + else + printf("lastlog agrees with the login time. This is a good thing.\n"); + +#endif + + printf("--\nThe output of 'last' shown next should have " + "an entry for root \n on %s for the time shown above:\n--\n", + stripline); + snprintf(cmdstring, sizeof(cmdstring), "last | grep '%s ' | head -3", + stripline); + system(cmdstring); + + printf("--\nEnd of login test.\n"); + + login_free_entry(li1); + + return 1; +} /* testAPI() */ + + +void +testLineName(char *line) +{ + /* have to null-terminate - these functions are designed for + * structures with fixed-length char arrays, and don't null-term.*/ + char full[17], strip[9], abbrev[5]; + + memset(full, '\0', sizeof(full)); + memset(strip, '\0', sizeof(strip)); + memset(abbrev, '\0', sizeof(abbrev)); + + line_fullname(full, line, sizeof(full)-1); + line_stripname(strip, full, sizeof(strip)-1); + line_abbrevname(abbrev, full, sizeof(abbrev)-1); + printf("%s: %s, %s, %s\n", line, full, strip, abbrev); + +} /* testLineName() */ + + +int +testOutput() +{ + printf("**\n** Testing linename functions\n**\n"); + testLineName("/dev/pts/1"); + testLineName("pts/1"); + testLineName("pts/999"); + testLineName("/dev/ttyp00"); + testLineName("ttyp00"); + + return 1; +} /* testOutput() */ + + +/* show which options got compiled in */ +void +showOptions(void) +{ + printf("**\n** Compile-time options\n**\n"); + + printf("login recording methods selected:\n"); +#ifdef USE_LOGIN + printf("\tUSE_LOGIN\n"); +#endif +#ifdef USE_UTMP + printf("\tUSE_UTMP (UTMP_FILE=%s)\n", UTMP_FILE); +#endif +#ifdef USE_UTMPX + printf("\tUSE_UTMPX (UTMPX_FILE=%s)\n", UTMPX_FILE); +#endif +#ifdef USE_WTMP + printf("\tUSE_WTMP (WTMP_FILE=%s)\n", WTMP_FILE); +#endif +#ifdef USE_WTMPX + printf("\tUSE_WTMPX (WTMPX_FILE=%s)\n", WTMPX_FILE); +#endif +#ifdef USE_LASTLOG + printf("\tUSE_LASTLOG (LASTLOG_FILE=%s)\n", LASTLOG_FILE); +#endif + printf("\n"); + +} /* showOptions() */ + + +int +main(int argc, char *argv[]) +{ + printf("Platform-independent login recording test driver\n"); + + __progname = get_progname(argv[0]); + if (argc == 2) { + if (strncmp(argv[1], "-i", 3) == 0) + compile_opts_only = 1; + else if (strncmp(argv[1], "-v", 3) == 0) + be_verbose=1; + } + + if (!compile_opts_only) { + if (be_verbose && !testOutput()) + return 1; + + if (!testAPI()) + return 1; + } + + showOptions(); + + return 0; +} /* main() */ + Index: src/crypto/openssh/mac.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/mac.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 mac.c --- src/crypto/openssh/mac.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/mac.c 30 Jun 2002 11:37:59 -0000 @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: mac.c,v 1.2 2001/04/05 10:42:51 markus Exp $"); +RCSID("$OpenBSD: mac.c,v 1.5 2002/05/16 22:02:50 markus Exp $"); #include @@ -36,7 +36,7 @@ struct { char *name; - EVP_MD * (*mdfunc)(void); + const EVP_MD * (*mdfunc)(void); int truncatebits; /* truncate digest if != 0 */ } macs[] = { { "hmac-sha1", EVP_sha1, 0, }, @@ -56,7 +56,7 @@ if (strcmp(name, macs[i].name) == 0) { if (mac != NULL) { mac->md = (*macs[i].mdfunc)(); - mac->key_len = mac->mac_len = mac->md->md_size; + mac->key_len = mac->mac_len = EVP_MD_size(mac->md); if (macs[i].truncatebits != 0) mac->mac_len = macs[i].truncatebits/8; } @@ -99,7 +99,7 @@ return (0); maclist = cp = xstrdup(names); for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; - (p = strsep(&cp, MAC_SEP))) { + (p = strsep(&cp, MAC_SEP))) { if (mac_init(NULL, p) < 0) { debug("bad mac %s [%s]", p, names); xfree(maclist); Index: src/crypto/openssh/mac.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/mac.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 mac.h --- src/crypto/openssh/mac.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/mac.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.h,v 1.1 2001/02/11 12:59:24 markus Exp $ */ +/* $OpenBSD: mac.h,v 1.3 2001/06/26 17:27:24 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -23,6 +23,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -int mac_valid(const char *names); -int mac_init(Mac *mac, char *name); -u_char *mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen); +int mac_valid(const char *); +int mac_init(Mac *, char *); +u_char *mac_compute(Mac *, u_int32_t, u_char *, int); Index: src/crypto/openssh/match.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/match.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 match.c --- src/crypto/openssh/match.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/match.c 30 Jun 2002 11:37:59 -0000 @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: match.c,v 1.12 2001/03/10 17:51:04 markus Exp $"); +RCSID("$OpenBSD: match.c,v 1.19 2002/03/01 13:12:10 markus Exp $"); #include "match.h" #include "xmalloc.h" @@ -104,14 +104,15 @@ } /* - * Tries to match the host name (which must be in all lowercase) against the + * Tries to match the string against the * comma-separated sequence of subpatterns (each possibly preceded by ! to * indicate negation). Returns -1 if negation matches, 1 if there is * a positive match, 0 if there is no match at all. */ int -match_hostname(const char *host, const char *pattern, u_int len) +match_pattern_list(const char *string, const char *pattern, u_int len, + int dolower) { char sub[1024]; int negated; @@ -132,9 +133,10 @@ * 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]; + i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; + subi++, i++) + sub[subi] = dolower && isupper(pattern[i]) ? + tolower(pattern[i]) : pattern[i]; /* If subpattern too long, return failure (no match). */ if (subi >= sizeof(sub) - 1) return 0; @@ -146,8 +148,8 @@ /* Null-terminate the subpattern. */ sub[subi] = '\0'; - /* Try to match the subpattern against the host name. */ - if (match_pattern(host, sub)) { + /* Try to match the subpattern against the string. */ + if (match_pattern(string, sub)) { if (negated) return -1; /* Negative */ else @@ -162,8 +164,69 @@ return got_positive; } +/* + * 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 -1 if negation matches, 1 if there is + * a positive match, 0 if there is no match at all. + */ +int +match_hostname(const char *host, const char *pattern, u_int len) +{ + return match_pattern_list(host, pattern, len, 1); +} -#define MAX_PROP 20 +/* + * returns 0 if we get a negative match for the hostname or the ip + * or if we get no match at all. returns 1 otherwise. + */ +int +match_host_and_ip(const char *host, const char *ipaddr, + const char *patterns) +{ + int mhost, mip; + + /* negative ipaddr match */ + if ((mip = match_hostname(ipaddr, patterns, strlen(patterns))) == -1) + return 0; + /* negative hostname match */ + if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1) + return 0; + /* no match at all */ + if (mhost == 0 && mip == 0) + return 0; + return 1; +} + +/* + * match user, user@host_or_ip, user@host_or_ip_list against pattern + */ +int +match_user(const char *user, const char *host, const char *ipaddr, + const char *pattern) +{ + char *p, *pat; + int ret; + + if ((p = strchr(pattern,'@')) == NULL) + return match_pattern(user, pattern); + + pat = xstrdup(pattern); + p = strchr(pat, '@'); + *p++ = '\0'; + + if ((ret = match_pattern(user, pat)) == 1) + ret = match_host_and_ip(host, ipaddr, p); + xfree(pat); + + return ret; +} + +/* + * Returns first item from client-list that is also supported by server-list, + * caller must xfree() returned string. + */ +#define MAX_PROP 40 #define SEP "," char * match_list(const char *client, const char *server, u_int *next) @@ -176,7 +239,7 @@ s = sp = xstrdup(server); for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0'; - (p = strsep(&sp, SEP)), i++) { + (p = strsep(&sp, SEP)), i++) { if (i < MAX_PROP) sproposals[i] = p; else @@ -185,7 +248,7 @@ nproposals = i; for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0'; - (p = strsep(&cp, SEP)), i++) { + (p = strsep(&cp, SEP)), i++) { for (j = 0; j < nproposals; j++) { if (strcmp(p, sproposals[j]) == 0) { ret = xstrdup(p); Index: src/crypto/openssh/match.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/match.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 match.h --- src/crypto/openssh/match.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/match.h 30 Jun 2002 11:37:59 -0000 @@ -1,11 +1,9 @@ -/* $OpenBSD: match.h,v 1.7 2001/03/10 17:51:04 markus Exp $ */ +/* $OpenBSD: match.h,v 1.12 2002/03/01 13:12:10 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved - * This file contains various auxiliary functions related to multiple - * precision integers. * * 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 @@ -16,24 +14,11 @@ #ifndef MATCH_H #define MATCH_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); - -/* - * 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 -1 if negation matches, 1 if there is - * a positive match, 0 if there is no match at all. - */ -int match_hostname(const char *host, const char *pattern, u_int len); - -/* - * Returns first item from client-list that is also supported by server-list, - * caller must xfree() returned string. - */ -char *match_list(const char *client, const char *server, u_int *next); +int match_pattern(const char *, const char *); +int match_pattern_list(const char *, const char *, u_int, int); +int match_hostname(const char *, const char *, u_int); +int match_host_and_ip(const char *, const char *, const char *); +int match_user(const char *, const char *, const char *, const char *); +char *match_list(const char *, const char *, u_int *); #endif Index: src/crypto/openssh/md5crypt.c =================================================================== RCS file: src/crypto/openssh/md5crypt.c diff -N src/crypto/openssh/md5crypt.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/md5crypt.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,159 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +/* + * Ported from FreeBSD to Linux, only minimal changes. --marekm + */ + +/* + * Adapted from shadow-19990607 by Tudor Bosman, tudorb@jm.nu + */ + +#include "includes.h" + +RCSID("$Id$"); + +#if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) + +#include + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static char *magic = "$1$"; /* + * This string is magic for + * this algorithm. Having + * it this way, we can get + * get better later on + */ + +static void +to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +int +is_md5_salt(const char *salt) +{ + return (!strncmp(salt, magic, strlen(magic))); +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char * +md5_crypt(const char *pw, const char *salt) +{ + static char passwd[120], *p; + static const char *sp,*ep; + unsigned char final[16]; + int sl,pl,i,j; + MD5_CTX ctx,ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(!strncmp(sp,magic,strlen(magic))) + sp += strlen(magic); + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + MD5_Init(&ctx); + + /* The password first, since that is what is most unknown */ + MD5_Update(&ctx,pw,strlen(pw)); + + /* Then our magic string */ + MD5_Update(&ctx,magic,strlen(magic)); + + /* Then the raw salt */ + MD5_Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5_Init(&ctx1); + MD5_Update(&ctx1,pw,strlen(pw)); + MD5_Update(&ctx1,sp,sl); + MD5_Update(&ctx1,pw,strlen(pw)); + MD5_Final(final,&ctx1); + for(pl = strlen(pw); pl > 0; pl -= 16) + MD5_Update(&ctx,final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (j=0,i = strlen(pw); i ; i >>= 1) + if(i&1) + MD5_Update(&ctx, final+j, 1); + else + MD5_Update(&ctx, pw+j, 1); + + /* Now make the output string */ + strcpy(passwd,magic); + strncat(passwd,sp,sl); + strcat(passwd,"$"); + + MD5_Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + MD5_Init(&ctx1); + if(i & 1) + MD5_Update(&ctx1,pw,strlen(pw)); + else + MD5_Update(&ctx1,final,16); + + if(i % 3) + MD5_Update(&ctx1,sp,sl); + + if(i % 7) + MD5_Update(&ctx1,pw,strlen(pw)); + + if(i & 1) + MD5_Update(&ctx1,final,16); + else + MD5_Update(&ctx1,pw,strlen(pw)); + MD5_Final(final,&ctx1); + } + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; + l = final[11] ; to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} + +#endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */ Index: src/crypto/openssh/md5crypt.h =================================================================== RCS file: src/crypto/openssh/md5crypt.h diff -N src/crypto/openssh/md5crypt.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/md5crypt.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,32 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +/* + * Ported from FreeBSD to Linux, only minimal changes. --marekm + */ + +/* + * Adapted from shadow-19990607 by Tudor Bosman, tudorb@jm.nu + */ + +/* $Id$ */ + +#ifndef _MD5CRYPT_H +#define _MD5CRYPT_H + +#include "config.h" + +#if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) + +int is_md5_salt(const char *salt); +char *md5_crypt(const char *pw, const char *salt); + +#endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */ + +#endif /* MD5CRYPT_H */ Index: src/crypto/openssh/mdoc2man.pl =================================================================== RCS file: src/crypto/openssh/mdoc2man.pl diff -N src/crypto/openssh/mdoc2man.pl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/mdoc2man.pl 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,592 @@ +#!/usr/bin/perl +### +### Quick usage: mdoc2man.pl < mdoc_manpage.8 > man_manpage.8 +### +### +### Copyright (c) 2001 University of Illinois Board of Trustees +### Copyright (c) 2001 Mark D. Roth +### 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 +### Illinois at Urbana, and their contributors. +### 4. The University nor the names of their +### contributors may be used to endorse or promote products derived from +### this software without specific prior written permission. +### +### THIS SOFTWARE IS PROVIDED BY THE TRUSTEES 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 TRUSTEES 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. +### + +use strict; + +my ($name, $date, $id); +my ($line); +my ($optlist, $oldoptlist, $nospace, $enum, $synopsis); +my ($reference, $block, $ext, $extopt, $literal); +my (@refauthors, $reftitle, $refissue, $refdate, $refopt); + + +$optlist = 0; ### 1 = bullet, 2 = enum, 3 = tag, 4 = item +$oldoptlist = 0; +$nospace = 0; +$synopsis = 0; +$reference = 0; +$block = 0; +$ext = 0; +$extopt = 0; +$literal = 0; + +while ($line = ) +{ + if ($line !~ /^\./) + { + print $line; + print ".br\n" + if ($literal); + next; + } + + $line =~ s/^\.//; + + next + if ($line =~ m/\\"/); + + $line = ParseMacro($line); + print($line) + if (defined $line); +} + + + +sub ParseMacro # ($line) +{ + my ($line) = @_; + my (@words, $retval, $option, $parens); + + @words = split(/\s+/, $line); + $retval = ''; + $option = 0; + $parens = 0; + +# print('@words = ', scalar(@words), ': ', join(' ', @words), "\n"); + + while ($_ = shift @words) + { +# print "WORD: $_\n"; + + next + if (/^(Li|Pf)$/); + + if (/^Xo$/) + { + $ext = 1; + $retval .= ' ' + if ($retval ne '' && $retval !~ m/[\n ]$/); + next; + } + + if (/^Xc$/) + { + $ext = 0; + $retval .= "\n" + if (! $extopt); + last; + } + + if (/^Bd$/) + { + $literal = 1 + if ($words[0] eq '-literal'); + $retval .= "\n"; + last; + } + + if (/^Ed$/) + { + $literal = 0; + last; + } + + if (/^Ns$/) + { + $nospace = 1 + if (! $nospace); + $retval =~ s/ $//; + next; + } + + if (/^No$/) + { + $retval =~ s/ $//; + $retval .= shift @words; + next; + } + + if (/^Dq$/) + { + $retval .= '``'; + do + { + $retval .= (shift @words) . ' '; + } + while (@words > 0 && $words[0] !~ m/^[\.,]/); + $retval =~ s/ $//; + $retval .= '\'\''; + $nospace = 1 + if (! $nospace && $words[0] =~ m/^[\.,]/); + next; + } + + if (/^(Sq|Ql)$/) + { + $retval .= '`' . (shift @words) . '\''; + $nospace = 1 + if (! $nospace && $words[0] =~ m/^[\.,]/); + next; + } + +# if (/^Ic$/) +# { +# $retval .= '\\fB' . shift(@words) . '\\fP'; +# next; +# } + + if (/^Oo$/) + { +# $retval .= "[\\c\n"; + $extopt = 1; + $nospace = 1 + if (! $nospace); + $retval .= '['; + next; + } + + if (/^Oc$/) + { + $extopt = 0; + $retval .= ']'; + next; + } + + $retval .= ' ' + if (! $nospace && $retval ne '' && $retval !~ m/[\n ]$/); + $nospace = 0 + if ($nospace == 1); + + if (/^Dd$/) + { + $date = join(' ', @words); + return undef; + } + + if (/^Dt$/) + { + $id = join(' ', @words); + return undef; + } + + if (/^Os$/) + { + $retval .= '.TH ' + . $id + . " \"$date\" \"" + . join(' ', @words) + . "\""; + last; + } + + if (/^Sh$/) + { + $retval .= '.SH'; + if ($words[0] eq 'SYNOPSIS') + { + $synopsis = 1; + } + else + { + $synopsis = 0; + } + next; + } + + if (/^Xr$/) + { + $retval .= '\\fB' . (shift @words) . + '\\fP(' . (shift @words) . ')' + . (shift @words); + last; + } + + if (/^Rs/) + { + @refauthors = (); + $reftitle = ''; + $refissue = ''; + $refdate = ''; + $refopt = ''; + $reference = 1; + last; + } + + if (/^Re/) + { + $retval .= "\n"; + + # authors + while (scalar(@refauthors) > 1) + { + $retval .= shift(@refauthors) . ', '; + } + $retval .= 'and ' + if ($retval ne ''); + $retval .= shift(@refauthors); + + # title + $retval .= ', \\fI' . $reftitle . '\\fP'; + + # issue + $retval .= ', ' . $refissue + if ($refissue ne ''); + + # date + $retval .= ', ' . $refdate + if ($refdate ne ''); + + # optional info + $retval .= ', ' . $refopt + if ($refopt ne ''); + + $retval .= ".\n"; + + $reference = 0; + last; + } + + if ($reference) + { + if (/^%A$/) + { + unshift(@refauthors, join(' ', @words)); + last; + } + + if (/^%T$/) + { + $reftitle = join(' ', @words); + $reftitle =~ s/^"//; + $reftitle =~ s/"$//; + last; + } + + if (/^%N$/) + { + $refissue = join(' ', @words); + last; + } + + if (/^%D$/) + { + $refdate = join(' ', @words); + last; + } + + if (/^%O$/) + { + $refopt = join(' ', @words); + last; + } + } + + if (/^Nm$/) + { + my $n = $name; + $n = shift @words + if (@words > 0); + $name = $n unless $name; + $retval .= ".br\n" + if ($synopsis); + $retval .= "\\fB$n\\fP"; + $nospace = 1 + if (! $nospace && $words[0] =~ m/^[\.,]/); + next; + } + + if (/^Nd$/) + { + $retval .= '\\-'; + next; + } + + if (/^Fl$/) + { + $retval .= '\\fB\\-' . (shift @words) . '\\fP'; + $nospace = 1 + if (! $nospace && $words[0] =~ m/^[\.,]/); + next; + } + + if (/^Ar$/) + { + $retval .= '\\fI'; + if (! defined $words[0]) + { + $retval .= 'file ...\\fP'; + } + else + { + $retval .= shift(@words) . '\\fP'; + while ($words[0] eq '|') + { + $retval .= ' ' . shift(@words); + $retval .= ' \\fI' . shift(@words); + $retval .= '\\fP'; + } + } + $nospace = 1 + if (! $nospace && $words[0] =~ m/^[\.,]/); + next; + } + + if (/^Cm$/) + { + $retval .= '\\fB' . (shift @words) . '\\fP'; + while ($words[0] =~ m/^[\.,:)]$/) + { + $retval .= shift(@words); + } + next; + } + + if (/^Op$/) + { + $option = 1; + $nospace = 1 + if (! $nospace); + $retval .= '['; +# my $tmp = pop(@words); +# $tmp .= ']'; +# push(@words, $tmp); + next; + } + + if (/^Pp$/) + { + $retval .= "\n"; + next; + } + + if (/^Ss$/) + { + $retval .= '.SS'; + next; + } + + if (/^Pa$/ && ! $option) + { + $retval .= '\\fI'; + $retval .= '\\&' + if ($words[0] =~ m/^\./); + $retval .= (shift @words) . '\\fP'; + while ($words[0] =~ m/^[\.,:;)]$/) + { + $retval .= shift(@words); + } +# $nospace = 1 +# if (! $nospace && $words[0] =~ m/^[\.,:)]/); + next; + } + + if (/^Dv$/) + { + $retval .= '.BR'; + next; + } + + if (/^(Em|Ev)$/) + { + $retval .= '.IR'; + next; + } + + if (/^Pq$/) + { + $retval .= '('; + $nospace = 1; + $parens = 1; + next; + } + + if (/^(S[xy])$/) + { + $retval .= '.B ' . join(' ', @words); + last; + } + + if (/^Ic$/) + { + $retval .= '\\fB'; + while (defined $words[0] + && $words[0] !~ m/^[\.,]/) + { + if ($words[0] eq 'Op') + { + shift(@words); + $retval .= '['; + my $tmp = pop(@words); + $tmp .= ']'; + push(@words, $tmp); + next; + } + if ($words[0] eq 'Ar') + { + shift @words; + $retval .= '\\fI'; + $retval .= shift @words; + $retval .= '\\fP'; + } + else + { + $retval .= shift @words; + } + $retval .= ' ' + if (! $nospace); + } + $retval =~ s/ $//; + $retval .= '\\fP'; + $retval .= shift @words + if (defined $words[0]); + last; + } + + if (/^Bl$/) + { + $oldoptlist = $optlist; + if ($words[0] eq '-bullet') + { + $optlist = 1; + } + elsif ($words[0] eq '-enum') + { + $optlist = 2; + $enum = 0; + } + elsif ($words[0] eq '-tag') + { + $optlist = 3; + } + elsif ($words[0] eq '-item') + { + $optlist = 4; + } + last; + } + + if (/^El$/) + { + $optlist = $oldoptlist; + next; + } + + if ($optlist && /^It$/) + { + if ($optlist == 1) + { + # bullets + $retval .= '.IP \\(bu'; + next; + } + + if ($optlist == 2) + { + # enum + $retval .= '.IP ' . (++$enum) . '.'; + next; + } + + if ($optlist == 3) + { + # tags + $retval .= ".TP\n"; + if ($words[0] =~ m/^(Pa|Ev)$/) + { + shift @words; + $retval .= '.B'; + } + next; + } + + if ($optlist == 4) + { + # item + $retval .= ".IP\n"; + next; + } + + next; + } + + if (/^Sm$/) + { + if ($words[0] eq 'off') + { + $nospace = 2; + } + elsif ($words[0] eq 'on') + { +# $retval .= "\n"; + $nospace = 0; + } + shift @words; + next; + } + + $retval .= "$_"; + } + + return undef + if ($retval eq '.'); + + $retval =~ s/^\.([^a-zA-Z])/$1/; +# $retval =~ s/ $//; + + $retval .= ')' + if ($parens == 1); + + $retval .= ']' + if ($option == 1); + +# $retval .= ' ' +# if ($nospace && $retval ne '' && $retval !~ m/\n$/); + +# $retval .= ' ' +# if ($extended && $retval !~ m/ $/); + + $retval .= ' ' + if ($ext && ! $extopt && $retval !~ m/ $/); + + $retval .= "\n" + if (! $ext && ! $extopt && $retval ne '' && $retval !~ m/\n$/); + + return $retval; +} + + Index: src/crypto/openssh/misc.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/misc.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 misc.c --- src/crypto/openssh/misc.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/misc.c 30 Jun 2002 11:37:59 -0000 @@ -1,5 +1,3 @@ -/* $OpenBSD: misc.c,v 1.5 2001/04/12 20:09:37 stevesk Exp $ */ - /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -25,18 +23,19 @@ */ #include "includes.h" -RCSID("$OpenBSD: misc.c,v 1.5 2001/04/12 20:09:37 stevesk Exp $"); +RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $"); #include "misc.h" #include "log.h" #include "xmalloc.h" +/* remove newline at end of string */ char * chop(char *s) { char *t = s; while (*t) { - if(*t == '\n' || *t == '\r') { + if (*t == '\n' || *t == '\r') { *t = '\0'; return s; } @@ -46,30 +45,75 @@ } +/* set/unset filedescriptor to non-blocking */ void set_nonblock(int fd) { int val; + val = fcntl(fd, F_GETFL, 0); if (val < 0) { error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); return; } if (val & O_NONBLOCK) { - debug("fd %d IS O_NONBLOCK", fd); + debug2("fd %d is O_NONBLOCK", fd); return; } debug("fd %d setting O_NONBLOCK", fd); val |= O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) - if (errno != ENODEV) - error("fcntl(%d, F_SETFL, O_NONBLOCK): %s", - fd, strerror(errno)); + debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", + fd, strerror(errno)); +} + +void +unset_nonblock(int fd) +{ + int val; + + val = fcntl(fd, F_GETFL, 0); + if (val < 0) { + error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); + return; + } + if (!(val & O_NONBLOCK)) { + debug2("fd %d is not O_NONBLOCK", fd); + return; + } + debug("fd %d clearing O_NONBLOCK", fd); + val &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, val) == -1) + debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", + fd, strerror(errno)); +} + +/* disable nagle on socket */ +void +set_nodelay(int fd) +{ + int opt; + socklen_t optlen; + + optlen = sizeof opt; + if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { + error("getsockopt TCP_NODELAY: %.100s", strerror(errno)); + return; + } + if (opt == 1) { + debug2("fd %d is TCP_NODELAY", fd); + return; + } + opt = 1; + debug("fd %d setting TCP_NODELAY", fd); + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) + error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); } /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" +/* return next token in configuration line */ char * strdelim(char **s) { @@ -108,13 +152,27 @@ copy->pw_gecos = xstrdup(pw->pw_gecos); copy->pw_uid = pw->pw_uid; copy->pw_gid = pw->pw_gid; +#ifdef HAVE_PW_EXPIRE_IN_PASSWD + copy->pw_expire = pw->pw_expire; +#endif +#ifdef HAVE_PW_CHANGE_IN_PASSWD + copy->pw_change = pw->pw_change; +#endif +#ifdef HAVE_PW_CLASS_IN_PASSWD copy->pw_class = xstrdup(pw->pw_class); +#endif copy->pw_dir = xstrdup(pw->pw_dir); copy->pw_shell = xstrdup(pw->pw_shell); return copy; } -int a2port(const char *s) +/* + * Convert ASCII string to TCP/IP port number. + * Port must be >0 and <=65535. + * Return 0 if invalid. + */ +int +a2port(const char *s) { long port; char *endp; @@ -127,4 +185,167 @@ return 0; return port; +} + +#define SECONDS 1 +#define MINUTES (SECONDS * 60) +#define HOURS (MINUTES * 60) +#define DAYS (HOURS * 24) +#define WEEKS (DAYS * 7) + +/* + * Convert a time string into seconds; format is + * a sequence of: + * time[qualifier] + * + * Valid time qualifiers are: + * seconds + * s|S seconds + * m|M minutes + * h|H hours + * d|D days + * w|W weeks + * + * Examples: + * 90m 90 minutes + * 1h30m 90 minutes + * 2d 2 days + * 1w 1 week + * + * Return -1 if time string is invalid. + */ +long +convtime(const char *s) +{ + long total, secs; + const char *p; + char *endp; + + errno = 0; + total = 0; + p = s; + + if (p == NULL || *p == '\0') + return -1; + + while (*p) { + secs = strtol(p, &endp, 10); + if (p == endp || + (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || + secs < 0) + return -1; + + switch (*endp++) { + case '\0': + endp--; + case 's': + case 'S': + break; + case 'm': + case 'M': + secs *= MINUTES; + break; + case 'h': + case 'H': + secs *= HOURS; + break; + case 'd': + case 'D': + secs *= DAYS; + break; + case 'w': + case 'W': + secs *= WEEKS; + break; + default: + return -1; + } + total += secs; + if (total < 0) + return -1; + p = endp; + } + + return total; +} + +char * +cleanhostname(char *host) +{ + if (*host == '[' && host[strlen(host) - 1] == ']') { + host[strlen(host) - 1] = '\0'; + return (host + 1); + } else + return host; +} + +char * +colon(char *cp) +{ + int flag = 0; + + if (*cp == ':') /* Leading colon is part of file name. */ + return (0); + if (*cp == '[') + flag = 1; + + for (; *cp; ++cp) { + if (*cp == '@' && *(cp+1) == '[') + flag = 1; + if (*cp == ']' && *(cp+1) == ':' && flag) + return (cp+1); + if (*cp == ':' && !flag) + return (cp); + if (*cp == '/') + return (0); + } + return (0); +} + +/* function to assist building execv() arguments */ +void +addargs(arglist *args, char *fmt, ...) +{ + va_list ap; + char buf[1024]; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + if (args->list == NULL) { + args->nalloc = 32; + args->num = 0; + } else if (args->num+2 >= args->nalloc) + args->nalloc *= 2; + + args->list = xrealloc(args->list, args->nalloc * sizeof(char *)); + args->list[args->num++] = xstrdup(buf); + args->list[args->num] = NULL; +} + +mysig_t +mysignal(int sig, mysig_t act) +{ +#ifdef HAVE_SIGACTION + struct sigaction sa, osa; + + if (sigaction(sig, NULL, &osa) == -1) + return (mysig_t) -1; + if (osa.sa_handler != act) { + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; +#if defined(SA_INTERRUPT) + if (sig == SIGALRM) + sa.sa_flags |= SA_INTERRUPT; +#endif + sa.sa_handler = act; + if (sigaction(sig, &sa, NULL) == -1) + return (mysig_t) -1; + } + return (osa.sa_handler); +#else + return (signal(sig, act)); +#endif } Index: src/crypto/openssh/misc.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/misc.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 misc.h --- src/crypto/openssh/misc.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/misc.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.4 2001/04/12 20:09:36 stevesk Exp $ */ +/* $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $ */ /* * Author: Tatu Ylonen @@ -11,20 +11,27 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ -/* remove newline at end of string */ -char *chop(char *s); -/* return next token in configuration line */ -char *strdelim(char **s); +char *chop(char *); +char *strdelim(char **); +void set_nonblock(int); +void unset_nonblock(int); +void set_nodelay(int); +int a2port(const char *); +char *cleanhostname(char *); +char *colon(char *); +long convtime(const char *); -/* set filedescriptor to non-blocking */ -void set_nonblock(int fd); +struct passwd *pwcopy(struct passwd *); -struct passwd * pwcopy(struct passwd *pw); +typedef struct arglist arglist; +struct arglist { + char **list; + int num; + int nalloc; +}; +void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3))); -/* - * Convert ASCII string to TCP/IP port number. - * Port must be >0 and <=65535. - * Return 0 if invalid. - */ -int a2port(const char *s); +/* wrapper for signal interface */ +typedef void (*mysig_t)(int); +mysig_t mysignal(int sig, mysig_t act); Index: src/crypto/openssh/mkinstalldirs =================================================================== RCS file: src/crypto/openssh/mkinstalldirs diff -N src/crypto/openssh/mkinstalldirs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/mkinstalldirs 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here Index: src/crypto/openssh/moduli =================================================================== RCS file: src/crypto/openssh/moduli diff -N src/crypto/openssh/moduli --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/moduli 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,158 @@ +# $OpenBSD: moduli,v 1.1 2001/06/22 22:07:54 provos Exp $ + +# Time Type Tests Tries Size Generator Modulus +20010328182134 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449C221CB +20010328182222 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449C95A43 +20010328182256 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449CC8CFB +20010328182409 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449D9BDB7 +20010328182628 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF5449FB6EF3 +20010328182708 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A000153 +20010328182758 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A06E9EB +20010328182946 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A1F2C93 +20010328183015 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A206ADB +20010328183112 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A2A109B +20010328183143 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A2BC1BB +20010328183301 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A3ADCEB +20010328183532 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A5E8BAF +20010328183646 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A6D54D7 +20010328183712 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544A6EC46F +20010328184223 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AB8626F +20010328184337 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AC7DC73 +20010328184634 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AEFF073 +20010328184714 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AF594FF +20010328184807 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544AFEEC53 +20010328184910 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B0B3513 +20010328185030 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B165707 +20010328185334 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B3A9673 +20010328185423 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B426623 +20010328185451 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B4427DB +20010328185637 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B5E3FC7 +20010328185720 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B65964B +20010328185757 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B6A9373 +20010328185844 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B7203B3 +20010328185933 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B7A9FFF +20010328190006 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B7DAAD3 +20010328190054 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B855C2F +20010328190139 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B8C53EB +20010328190304 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544B9F26C3 +20010328190329 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BA00697 +20010328190412 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BA54313 +20010328190506 2 6 100 1023 5 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BAEEF27 +20010328190550 2 6 100 1023 2 DCFAC4EFE89F5B082962AB9A67E8D63E84FA491E5D3874978815868595469163DA0661E6208A8C2CD4F83893B53864ADFD2154E8D8EFA146BAD808562E4BF6C90348FD79EEB3387D93FC7943BC450BA55399BA3CF3DFBD0D4E71800007B0E9D5F12E7A2CB7EA4E49812E715F8DC570C478DC2DEB1C49B0AE87A5DF544BB5CE0B +20010328200734 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC33395187 +20010328201124 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC334ED15B +20010328201358 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3359FC07 +20010328201537 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC335F7A83 +20010328201829 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC336D1433 +20010328202120 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC337B253B +20010328202848 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC33A3D43F +20010328203335 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC33BF24A3 +20010328204332 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC34011B8B +20010328204443 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3402A92F +20010328204617 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3406D343 +20010328205458 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3436FA2B +20010328210413 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3471CF1B +20010328213513 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC352AF5EF +20010328215014 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC358CC3CB +20010328215520 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35A9B7FF +20010328215733 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35B2927F +20010328220114 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35C47323 +20010328220334 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35CFA9C3 +20010328220653 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35E0BB37 +20010328220915 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35E9CC23 +20010328221256 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC35FD7D67 +20010328221457 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC36052CCB +20010328222639 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC364A1E07 +20010328224126 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC36AD5557 +20010328225125 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC36EE57BF +20010328225751 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3716A70B +20010328225943 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC371D010B +20010328230054 2 6 100 1534 5 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC371EB5C7 +20010328230301 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC37275F4B +20010328230628 2 6 100 1534 2 6DFD16D9669EDAF42EF5D4EED82AA84B0541DEC2045B6AF55021A184F32BCADE614A114137022C9A8B41C09AFC38199E7305864F70A8708F37FC2127264ECF4FA32391F243CC62B89602D3813082679E5BDF496BA9DFA4C818AD21EC261B6F11841E6F2DE1574CE95095841DAF052868CCD5E9BFCA543E0934B50A76A598E693136DE2D479AEF3785D97BAFF4FB85AB8D46DA424C4CC5E11ABCAF718837E16350982BF8A27728318EC02C71ED164F57CDB121B72614B7B7C406613EC3738C3F3 +20010329000424 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853ACAACAB +20010329001637 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853AE5BE0F +20010329002229 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853AEDE2D3 +20010329003652 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853B0F32CB +20010329005040 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853B30E503 +20010329014643 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853BC9AF57 +20010329021950 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853C205263 +20010329023256 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853C3F2E53 +20010329031049 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853CA28BBF +20010329032045 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853CB81103 +20010329052113 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853DF13B47 +20010329052449 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853DF3ED53 +20010329060404 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853E5D25E7 +20010329062856 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853E9CF013 +20010329063152 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853E9E1CEB +20010329070601 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853EF58B7F +20010329071302 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F017697 +20010329072011 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F0E72D3 +20010329072445 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F14CE17 +20010329073641 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F2EEBA3 +20010329075209 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F52E927 +20010329080750 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853F776F8B +20010329084002 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853FC98043 +20010329084744 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853FD7EAAF +20010329090209 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993853FF9AF5F +20010329093527 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385404E330B +20010329094652 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938540672D1F +20010329103445 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938540E4B213 +20010329111418 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC34993854144947F +20010329112031 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385414F223B +20010329112413 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938541522073 +20010329114209 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385417C8E53 +20010329125026 2 6 100 2046 2 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385422E41AB +20010329132045 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC3499385427DD3FF +20010329134105 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938542AFA2D7 +20010329134914 2 6 100 2046 5 7ED0888B660A818F15E5F76A7F2BF10C99D74129DA04446C60116C9C800501060B8AFF075DCE0C08CEFDF695440E6F16FCCDB06359D080EF62D6485CBAEB94B92BE771D535B4EA9C5D14D84CD7649E25C7CFEA2C914486CC2BFDE77C4C0DF1D6DDED65FEE2F53A7FA690AFE38EE00C154FBAEFF935466B176CB0AED02458A552929F4EA7FC3E6F9F758DE7F22CC1F49641F492820441BDC109F0CE18F883FC93EA9AC4C1432682BA1C5B67BED8C861152A5F952A8CDCF1BCE02B8D93E80C113CE9FE2E4ACA49B2978B99A8C5FA231A77F5E7C604D44C7C6EA98D561294D4F7AB061432CAB8BBDCEC3659DE64F65265E6B9FC5F46879BB17CC349938542C04A37 +20010403222140 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0AB16DAF +20010403225231 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0AC56CFF +20010404053436 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0C2F4B7F +20010404092851 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D04E7F7 +20010404093943 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D07794B +20010404102659 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D2BE8CF +20010404112553 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0D5D012B +20010404174625 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0EA59E17 +20010404184645 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0ED6DA4F +20010404193402 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0EFB39B3 +20010404230716 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B0FB07C1B +20010405044433 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B10DD9FC3 +20010405053429 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B11038737 +20010405062826 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B112E24E7 +20010405092601 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B11C9E9FB +20010405113007 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B123803EB +20010405122212 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B12612ED3 +20010405182035 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B13A25087 +20010405210758 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B142C4E23 +20010405220222 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B145878F3 +20010406020130 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B152AF6AB +20010406053538 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B15E78C8B +20010406073014 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1649BFEF +20010406074100 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B164D4E3F +20010406103625 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B16E07B33 +20010406131946 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B17706243 +20010406170234 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B182FD957 +20010406182949 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B18768903 +20010406203157 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B18DCFC3B +20010407022825 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1A1AF797 +20010407071024 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1B1551E7 +20010407112402 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1BF78EC7 +20010407123215 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1C30021B +20010407161504 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1CF27743 +20010407171629 2 6 100 3190 5 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1D25FAD7 +20010407191502 2 6 100 3190 2 669BA3ED661F226A090BE5644A2BB4209371B78FC3E6848A095821993F59084CA5EE12052F977D01F0666F03F6573B199DFEC9AB94588C2C60DE3B3E7CF5094587919FCC3FB40A61C261E891A0F91D9FFC8F30CA12CF809DD8290DD786FA8B041FFAC5793C38F38757EA6790472AC2692185B554B0046E8C065C983C0ACC8D2F85AB4BEDF7CE233009218C9691FE44261580D4149F1D4471B0B5DF79E224252474EBC3B7B5490950BB438BF498E79F8794498B3A3B5FBB42829C3BBEA4067F28C23BE40377B986BD5443CCCF02405B8CCCAA09E8179F0168D4969994171A6AD98F81015BC84E10A44E1EFD2E0862C5D1AAFE99014715A36800DBD9A6C51C0226CC82A651DAE4F73D54C4D103C13D1C15CF8CCA67D5CB39F03C66F3B7467F8FFDCC5074CD0C1B2538FBF956971BF39314CEDD20E1B10DE16D86E10BE7FA5B1A706AEB4C356F49807A22072CD00559AF0A863788956651919E26A315EAD1D26E7C98FC4CFA35A0F04DD400A2991A1FFE5B271FEDE54375896A29F968BE1D511BA466A92AC3E3772709FC815B1D8C2753 +20010420002705 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10C1E08F3 +20010420005243 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10C219FB3 +20010420035225 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10C660B3F +20010420145749 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10D741313 +20010420205718 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10DD41193 +20010420232458 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10E0AB4EF +20010421003952 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10E22F857 +20010421013245 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10E31828B +20010421085157 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10EE28B2B +20010421092617 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10EE97A3B +20010421135621 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C10F52C463 +20010422012438 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C110627AF3 +20010422042530 2 6 100 4094 2 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C110A793B3 +20010422163438 2 6 100 4094 5 65B5B9F5ECFADB4CCB38D1BC894302E95B4843290F1A7A40579DF3E2FF98C1D3DA9F210857C784433DF32ADF9E0C80121211690E1FFB41B8DB4E86AFE388A09C9BB2C98EDC581C2E65D57F61BB920C3D1B7B058B5FADFF65D607DAFF443B8BA1ACE1A3A7B16EA0713F62537C6689E3C4A0F61198F3B054FCF140CFADD8622C0E7621998331E59DA6F72E9D608D0E58F526E95F485C7CA30A416617DA3CCFF722BB82362606283D054B34B83ECDB4C91BAB835944010EBE5E9FA7B016ED89891DD553CC71B5CF76EDB2A184B377F670D6AF191763EEFD175E48EA37EE18B9E44E2D017D845C444C8111816819866E490B52F7F879A0C6F401CF7859674F93E304365F4E8CB8C312EFB725732A46D7CF0C9D2939AEE25F428CEFC90959DBF8ADD612F343EF9BFCA2FBA61BD4BF93E1E54626D227FDA812E18D071579AB4EEAC9901DAB183BCB0D9F48732D92CE66B386EAE5D8212C9FD156DC3F09B171B5603E17A468D244F3B6880EBCDA189BA9E23E4A4C6C2995ACF264F8CE9D54B27316343C0BC19221F75E6A2AC68011741695E599F73460B7A042E0461DB189CDCE223B40336BF2251AE3B363159960C9F63B47EFC43790D474DABB9A686DAF21E0DD76533749FCA9F144FA9C243CEF1364C79D981ED81DC4635C73B7F8908BA190AA920ED370F815BC2F9B3D28ED87BE34A01498836222C17B70C246C03CA1C111D2A227 Index: src/crypto/openssh/monitor.c =================================================================== RCS file: src/crypto/openssh/monitor.c diff -N src/crypto/openssh/monitor.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,1653 @@ +/* + * Copyright 2002 Niels Provos + * Copyright 2002 Markus Friedl + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: monitor.c,v 1.18 2002/06/26 13:20:57 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/monitor.c,v 1.6 2002/06/29 11:48:58 des Exp $"); + +#include + +#ifdef SKEY +#ifdef OPIE +#include +#define skey opie +#define skeychallenge(k, u, c) opiechallenge((k), (u), (c)) +#define skey_haskey(u) opie_haskey((u)) +#define skey_passcheck(u, r) opie_passverify((u), (r)) +#else +#include +#endif +#endif + +#include "ssh.h" +#include "auth.h" +#include "kex.h" +#include "dh.h" +#include "zlib.h" +#include "packet.h" +#include "auth-options.h" +#include "sshpty.h" +#include "channels.h" +#include "session.h" +#include "sshlogin.h" +#include "canohost.h" +#include "log.h" +#include "servconf.h" +#include "monitor.h" +#include "monitor_mm.h" +#include "monitor_wrap.h" +#include "monitor_fdpass.h" +#include "xmalloc.h" +#include "misc.h" +#include "buffer.h" +#include "bufaux.h" +#include "compat.h" +#include "ssh2.h" +#include "mpaux.h" + +/* Imports */ +extern ServerOptions options; +extern u_int utmp_len; +extern Newkeys *current_keys[]; +extern z_stream incoming_stream; +extern z_stream outgoing_stream; +extern u_char session_id[]; +extern Buffer input, output; +extern Buffer auth_debug; +extern int auth_debug_init; + +/* State exported from the child */ + +struct { + z_stream incoming; + z_stream outgoing; + u_char *keyin; + u_int keyinlen; + u_char *keyout; + u_int keyoutlen; + u_char *ivin; + u_int ivinlen; + u_char *ivout; + u_int ivoutlen; + u_char *ssh1key; + u_int ssh1keylen; + int ssh1cipher; + int ssh1protoflags; + u_char *input; + u_int ilen; + u_char *output; + u_int olen; +} child_state; + +/* Functions on the montior that answer unprivileged requests */ + +int mm_answer_moduli(int, Buffer *); +int mm_answer_sign(int, Buffer *); +int mm_answer_pwnamallow(int, Buffer *); +int mm_answer_auth2_read_banner(int, Buffer *); +int mm_answer_authserv(int, Buffer *); +int mm_answer_authpassword(int, Buffer *); +int mm_answer_bsdauthquery(int, Buffer *); +int mm_answer_bsdauthrespond(int, Buffer *); +int mm_answer_skeyquery(int, Buffer *); +int mm_answer_skeyrespond(int, Buffer *); +int mm_answer_keyallowed(int, Buffer *); +int mm_answer_keyverify(int, Buffer *); +int mm_answer_pty(int, Buffer *); +int mm_answer_pty_cleanup(int, Buffer *); +int mm_answer_term(int, Buffer *); +int mm_answer_rsa_keyallowed(int, Buffer *); +int mm_answer_rsa_challenge(int, Buffer *); +int mm_answer_rsa_response(int, Buffer *); +int mm_answer_sesskey(int, Buffer *); +int mm_answer_sessid(int, Buffer *); + +#ifdef USE_PAM +int mm_answer_pam_start(int, Buffer *); +int mm_answer_pam_init_ctx(int, Buffer *); +int mm_answer_pam_query(int, Buffer *); +int mm_answer_pam_respond(int, Buffer *); +int mm_answer_pam_free_ctx(int, Buffer *); +#endif + +static Authctxt *authctxt; +static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ + +/* local state for key verify */ +static u_char *key_blob = NULL; +static u_int key_bloblen = 0; +static int key_blobtype = MM_NOKEY; +static u_char *hostbased_cuser = NULL; +static u_char *hostbased_chost = NULL; +static char *auth_method = "unknown"; +static int session_id2_len = 0; +static u_char *session_id2 = NULL; + +struct mon_table { + enum monitor_reqtype type; + int flags; + int (*f)(int, Buffer *); +}; + +#define MON_ISAUTH 0x0004 /* Required for Authentication */ +#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */ +#define MON_ONCE 0x0010 /* Disable after calling */ + +#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE) + +#define MON_PERMIT 0x1000 /* Request is permitted */ + +struct mon_table mon_dispatch_proto20[] = { + {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, + {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, + {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, + {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, + {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, +#ifdef USE_PAM + {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, + {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, + {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, + {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, +#endif +#ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, + {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, +#endif +#ifdef SKEY + {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, + {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, +#endif + {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, + {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, + {0, 0, NULL} +}; + +struct mon_table mon_dispatch_postauth20[] = { + {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, + {MONITOR_REQ_SIGN, 0, mm_answer_sign}, + {MONITOR_REQ_PTY, 0, mm_answer_pty}, + {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, + {MONITOR_REQ_TERM, 0, mm_answer_term}, + {0, 0, NULL} +}; + +struct mon_table mon_dispatch_proto15[] = { + {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, + {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, + {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, + {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed}, + {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, + {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, + {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, +#ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, + {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond}, +#endif +#ifdef SKEY + {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, + {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, +#endif +#ifdef USE_PAM + {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, + {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, + {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, + {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, +#endif + {0, 0, NULL} +}; + +struct mon_table mon_dispatch_postauth15[] = { + {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, + {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, + {MONITOR_REQ_TERM, 0, mm_answer_term}, + {0, 0, NULL} +}; + +struct mon_table *mon_dispatch; + +/* Specifies if a certain message is allowed at the moment */ + +static void +monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit) +{ + while (ent->f != NULL) { + if (ent->type == type) { + ent->flags &= ~MON_PERMIT; + ent->flags |= permit ? MON_PERMIT : 0; + return; + } + ent++; + } +} + +static void +monitor_permit_authentications(int permit) +{ + struct mon_table *ent = mon_dispatch; + + while (ent->f != NULL) { + if (ent->flags & MON_AUTH) { + ent->flags &= ~MON_PERMIT; + ent->flags |= permit ? MON_PERMIT : 0; + } + ent++; + } +} + +Authctxt * +monitor_child_preauth(struct monitor *pmonitor) +{ + struct mon_table *ent; + int authenticated = 0; + + debug3("preauth child monitor started"); + + if (compat20) { + mon_dispatch = mon_dispatch_proto20; + + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + } else { + mon_dispatch = mon_dispatch_proto15; + + monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); + } + + authctxt = authctxt_new(); + + /* The first few requests do not require asynchronous access */ + while (!authenticated) { + authenticated = monitor_read(pmonitor, mon_dispatch, &ent); + if (authenticated) { + if (!(ent->flags & MON_AUTHDECIDE)) + fatal("%s: unexpected authentication from %d", + __func__, ent->type); + if (authctxt->pw->pw_uid == 0 && + !auth_root_allowed(auth_method)) + authenticated = 0; + } + + if (ent->flags & MON_AUTHDECIDE) { + auth_log(authctxt, authenticated, auth_method, + compat20 ? " ssh2" : ""); + if (!authenticated) + authctxt->failures++; + } + } + + if (!authctxt->valid) + fatal("%s: authenticated invalid user", __func__); + + debug("%s: %s has been authenticated by privileged process", + __func__, authctxt->user); + + mm_get_keystate(pmonitor); + + return (authctxt); +} + +void +monitor_child_postauth(struct monitor *pmonitor) +{ + if (compat20) { + mon_dispatch = mon_dispatch_postauth20; + + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); + + } else { + mon_dispatch = mon_dispatch_postauth15; + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); + } + if (!no_pty_flag) { + monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); + } + + for (;;) + monitor_read(pmonitor, mon_dispatch, NULL); +} + +void +monitor_sync(struct monitor *pmonitor) +{ + if (options.compression) { + /* The member allocation is not visible, so sync it */ + mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback); + } +} + +int +monitor_read(struct monitor *pmonitor, struct mon_table *ent, + struct mon_table **pent) +{ + Buffer m; + int ret; + u_char type; + + buffer_init(&m); + + mm_request_receive(pmonitor->m_sendfd, &m); + type = buffer_get_char(&m); + + debug3("%s: checking request %d", __func__, type); + + while (ent->f != NULL) { + if (ent->type == type) + break; + ent++; + } + + if (ent->f != NULL) { + if (!(ent->flags & MON_PERMIT)) + fatal("%s: unpermitted request %d", __func__, + type); + ret = (*ent->f)(pmonitor->m_sendfd, &m); + buffer_free(&m); + + /* The child may use this request only once, disable it */ + if (ent->flags & MON_ONCE) { + debug2("%s: %d used once, disabling now", __func__, + type); + ent->flags &= ~MON_PERMIT; + } + + if (pent != NULL) + *pent = ent; + + return ret; + } + + fatal("%s: unsupported request: %d", __func__, type); + + /* NOTREACHED */ + return (-1); +} + +/* allowed key state */ +static int +monitor_allowed_key(u_char *blob, u_int bloblen) +{ + /* make sure key is allowed */ + if (key_blob == NULL || key_bloblen != bloblen || + memcmp(key_blob, blob, key_bloblen)) + return (0); + return (1); +} + +static void +monitor_reset_key_state(void) +{ + /* reset state */ + if (key_blob != NULL) + xfree(key_blob); + if (hostbased_cuser != NULL) + xfree(hostbased_cuser); + if (hostbased_chost != NULL) + xfree(hostbased_chost); + key_blob = NULL; + key_bloblen = 0; + key_blobtype = MM_NOKEY; + hostbased_cuser = NULL; + hostbased_chost = NULL; +} + +int +mm_answer_moduli(int socket, Buffer *m) +{ + DH *dh; + int min, want, max; + + min = buffer_get_int(m); + want = buffer_get_int(m); + max = buffer_get_int(m); + + debug3("%s: got parameters: %d %d %d", + __func__, min, want, max); + /* We need to check here, too, in case the child got corrupted */ + if (max < min || want < min || max < want) + fatal("%s: bad parameters: %d %d %d", + __func__, min, want, max); + + buffer_clear(m); + + dh = choose_dh(min, want, max); + if (dh == NULL) { + buffer_put_char(m, 0); + return (0); + } else { + /* Send first bignum */ + buffer_put_char(m, 1); + buffer_put_bignum2(m, dh->p); + buffer_put_bignum2(m, dh->g); + + DH_free(dh); + } + mm_request_send(socket, MONITOR_ANS_MODULI, m); + return (0); +} + +int +mm_answer_sign(int socket, Buffer *m) +{ + Key *key; + u_char *p; + u_char *signature; + u_int siglen, datlen; + int keyid; + + debug3("%s", __func__); + + keyid = buffer_get_int(m); + p = buffer_get_string(m, &datlen); + + if (datlen != 20) + fatal("%s: data length incorrect: %d", __func__, datlen); + + /* save session id, it will be passed on the first call */ + if (session_id2_len == 0) { + session_id2_len = datlen; + session_id2 = xmalloc(session_id2_len); + memcpy(session_id2, p, session_id2_len); + } + + if ((key = get_hostkey_by_index(keyid)) == NULL) + fatal("%s: no hostkey from index %d", __func__, keyid); + if (key_sign(key, &signature, &siglen, p, datlen) < 0) + fatal("%s: key_sign failed", __func__); + + debug3("%s: signature %p(%d)", __func__, signature, siglen); + + buffer_clear(m); + buffer_put_string(m, signature, siglen); + + xfree(p); + xfree(signature); + + mm_request_send(socket, MONITOR_ANS_SIGN, m); + + /* Turn on permissions for getpwnam */ + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); + + return (0); +} + +/* Retrieves the password entry and also checks if the user is permitted */ + +int +mm_answer_pwnamallow(int socket, Buffer *m) +{ + char *login; + struct passwd *pwent; + int allowed = 0; + + debug3("%s", __func__); + + if (authctxt->attempt++ != 0) + fatal("%s: multiple attempts for getpwnam", __func__); + + login = buffer_get_string(m, NULL); + + pwent = getpwnamallow(login); + + authctxt->user = xstrdup(login); + setproctitle("%s [priv]", pwent ? login : "unknown"); + xfree(login); + + buffer_clear(m); + + if (pwent == NULL) { + buffer_put_char(m, 0); + goto out; + } + + allowed = 1; + authctxt->pw = pwent; + authctxt->valid = 1; + + buffer_put_char(m, 1); + buffer_put_string(m, pwent, sizeof(struct passwd)); + buffer_put_cstring(m, pwent->pw_name); + buffer_put_cstring(m, "*"); + buffer_put_cstring(m, pwent->pw_gecos); +#ifdef HAVE_PW_CLASS_IN_PASSWD + buffer_put_cstring(m, pwent->pw_class); +#endif + buffer_put_cstring(m, pwent->pw_dir); + buffer_put_cstring(m, pwent->pw_shell); + + out: + debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); + mm_request_send(socket, MONITOR_ANS_PWNAM, m); + + /* For SSHv1 allow authentication now */ + if (!compat20) + monitor_permit_authentications(1); + else { + /* Allow service/style information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); + } + +#ifdef USE_PAM + monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); +#endif + + return (0); +} + +int mm_answer_auth2_read_banner(int socket, Buffer *m) +{ + char *banner; + + buffer_clear(m); + banner = auth2_read_banner(); + buffer_put_cstring(m, banner != NULL ? banner : ""); + mm_request_send(socket, MONITOR_ANS_AUTH2_READ_BANNER, m); + + if (banner != NULL) + free(banner); + + return (0); +} + +int +mm_answer_authserv(int socket, Buffer *m) +{ + monitor_permit_authentications(1); + + authctxt->service = buffer_get_string(m, NULL); + authctxt->style = buffer_get_string(m, NULL); + debug3("%s: service=%s, style=%s", + __func__, authctxt->service, authctxt->style); + + if (strlen(authctxt->style) == 0) { + xfree(authctxt->style); + authctxt->style = NULL; + } + + return (0); +} + +int +mm_answer_authpassword(int socket, Buffer *m) +{ + static int call_count; + char *passwd; + int authenticated, plen; + + passwd = buffer_get_string(m, &plen); + /* Only authenticate if the context is valid */ + authenticated = options.password_authentication && + authctxt->valid && auth_password(authctxt, passwd); + memset(passwd, 0, strlen(passwd)); + xfree(passwd); + + buffer_clear(m); + buffer_put_int(m, authenticated); + + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m); + + call_count++; + if (plen == 0 && call_count == 1) + auth_method = "none"; + else + auth_method = "password"; + + /* Causes monitor loop to terminate if authenticated */ + return (authenticated); +} + +#ifdef BSD_AUTH +int +mm_answer_bsdauthquery(int socket, Buffer *m) +{ + char *name, *infotxt; + u_int numprompts; + u_int *echo_on; + char **prompts; + int res; + + res = bsdauth_query(authctxt, &name, &infotxt, &numprompts, + &prompts, &echo_on); + + buffer_clear(m); + buffer_put_int(m, res); + if (res != -1) + buffer_put_cstring(m, prompts[0]); + + debug3("%s: sending challenge res: %d", __func__, res); + mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m); + + if (res != -1) { + xfree(name); + xfree(infotxt); + xfree(prompts); + xfree(echo_on); + } + + return (0); +} + +int +mm_answer_bsdauthrespond(int socket, Buffer *m) +{ + char *response; + int authok; + + if (authctxt->as == 0) + fatal("%s: no bsd auth session", __func__); + + response = buffer_get_string(m, NULL); + authok = options.challenge_response_authentication && + auth_userresponse(authctxt->as, response, 0); + authctxt->as = NULL; + debug3("%s: <%s> = <%d>", __func__, response, authok); + xfree(response); + + buffer_clear(m); + buffer_put_int(m, authok); + + debug3("%s: sending authenticated: %d", __func__, authok); + mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m); + + auth_method = "bsdauth"; + + return (authok != 0); +} +#endif + +#ifdef SKEY +int +mm_answer_skeyquery(int socket, Buffer *m) +{ + struct skey skey; + char challenge[1024]; + int res; + + res = skeychallenge(&skey, authctxt->user, challenge); + + buffer_clear(m); + buffer_put_int(m, res); + if (res != -1) + buffer_put_cstring(m, challenge); + + debug3("%s: sending challenge res: %d", __func__, res); + mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); + + return (0); +} + +int +mm_answer_skeyrespond(int socket, Buffer *m) +{ + char *response; + int authok; + + response = buffer_get_string(m, NULL); + + authok = (options.challenge_response_authentication && + authctxt->valid && + skey_haskey(authctxt->pw->pw_name) == 0 && + skey_passcheck(authctxt->pw->pw_name, response) != -1); + + xfree(response); + + buffer_clear(m); + buffer_put_int(m, authok); + + debug3("%s: sending authenticated: %d", __func__, authok); + mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m); + + auth_method = "skey"; + + return (authok != 0); +} +#endif + +#ifdef USE_PAM +int +mm_answer_pam_start(int socket, Buffer *m) +{ + char *user; + + user = buffer_get_string(m, NULL); + + start_pam(user); + + xfree(user); + + return (0); +} + +static void *pam_ctxt, *pam_authok; +extern KbdintDevice pam_device; + +int +mm_answer_pam_init_ctx(int socket, Buffer *m) +{ + + debug3("%s", __func__); + authctxt->user = buffer_get_string(m, NULL); + pam_ctxt = (pam_device.init_ctx)(authctxt); + pam_authok = NULL; + buffer_clear(m); + if (pam_ctxt != NULL) { + monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1); + buffer_put_int(m, 1); + } else { + buffer_put_int(m, 0); + } + mm_request_send(socket, MONITOR_ANS_PAM_INIT_CTX, m); + return (0); +} + +int +mm_answer_pam_query(int socket, Buffer *m) +{ + char *name, *info, **prompts; + u_int num, *echo_on; + int i, ret; + + debug3("%s", __func__); + pam_authok = NULL; + ret = (pam_device.query)(pam_ctxt, &name, &info, &num, &prompts, &echo_on); + if (num > 1 || name == NULL || info == NULL) + ret = -1; + buffer_put_int(m, ret); + buffer_put_cstring(m, name); + xfree(name); + buffer_put_cstring(m, info); + xfree(info); + buffer_put_int(m, num); + for (i = 0; i < num; ++i) { + buffer_put_cstring(m, prompts[i]); + xfree(prompts[i]); + buffer_put_int(m, echo_on[i]); + } + if (prompts != NULL) + xfree(prompts); + if (echo_on != NULL) + xfree(echo_on); + mm_request_send(socket, MONITOR_ANS_PAM_QUERY, m); + return (0); +} + +int +mm_answer_pam_respond(int socket, Buffer *m) +{ + char **resp; + u_int num; + int i, ret; + + debug3("%s", __func__); + pam_authok = NULL; + num = buffer_get_int(m); + if (num > 0) { + resp = xmalloc(num * sizeof(char *)); + for (i = 0; i < num; ++i) + resp[i] = buffer_get_string(m, NULL); + ret = (pam_device.respond)(pam_ctxt, num, resp); + for (i = 0; i < num; ++i) + xfree(resp[i]); + xfree(resp); + } else { + ret = (pam_device.respond)(pam_ctxt, num, NULL); + } + buffer_clear(m); + buffer_put_int(m, ret); + mm_request_send(socket, MONITOR_ANS_PAM_RESPOND, m); + auth_method = "keyboard-interactive/pam"; + if (ret == 0) + pam_authok = pam_ctxt; + return (ret); +} + +int +mm_answer_pam_free_ctx(int socket, Buffer *m) +{ + + debug3("%s", __func__); + (pam_device.free_ctx)(pam_ctxt); + buffer_clear(m); + mm_request_send(socket, MONITOR_ANS_PAM_FREE_CTX, m); + return (pam_authok == pam_ctxt); +} +#endif + +static void +mm_append_debug(Buffer *m) +{ + if (auth_debug_init && buffer_len(&auth_debug)) { + debug3("%s: Appending debug messages for child", __func__); + buffer_append(m, buffer_ptr(&auth_debug), + buffer_len(&auth_debug)); + buffer_clear(&auth_debug); + } +} + +int +mm_answer_keyallowed(int socket, Buffer *m) +{ + Key *key; + u_char *cuser, *chost, *blob; + u_int bloblen; + enum mm_keytype type = 0; + int allowed = 0; + + debug3("%s entering", __func__); + + type = buffer_get_int(m); + cuser = buffer_get_string(m, NULL); + chost = buffer_get_string(m, NULL); + blob = buffer_get_string(m, &bloblen); + + key = key_from_blob(blob, bloblen); + + if ((compat20 && type == MM_RSAHOSTKEY) || + (!compat20 && type != MM_RSAHOSTKEY)) + fatal("%s: key type and protocol mismatch", __func__); + + debug3("%s: key_from_blob: %p", __func__, key); + + if (key != NULL && authctxt->pw != NULL) { + switch(type) { + case MM_USERKEY: + allowed = options.pubkey_authentication && + user_key_allowed(authctxt->pw, key); + break; + case MM_HOSTKEY: + allowed = options.hostbased_authentication && + hostbased_key_allowed(authctxt->pw, + cuser, chost, key); + break; + case MM_RSAHOSTKEY: + key->type = KEY_RSA1; /* XXX */ + allowed = options.rhosts_rsa_authentication && + auth_rhosts_rsa_key_allowed(authctxt->pw, + cuser, chost, key); + break; + default: + fatal("%s: unknown key type %d", __func__, type); + break; + } + key_free(key); + } + + /* clear temporarily storage (used by verify) */ + monitor_reset_key_state(); + + if (allowed) { + /* Save temporarily for comparison in verify */ + key_blob = blob; + key_bloblen = bloblen; + key_blobtype = type; + hostbased_cuser = cuser; + hostbased_chost = chost; + } + + debug3("%s: key %p is %s", + __func__, key, allowed ? "allowed" : "disallowed"); + + buffer_clear(m); + buffer_put_int(m, allowed); + + mm_append_debug(m); + + mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m); + + if (type == MM_RSAHOSTKEY) + monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); + + return (0); +} + +static int +monitor_valid_userblob(u_char *data, u_int datalen) +{ + Buffer b; + u_char *p; + u_int len; + int fail = 0; + + buffer_init(&b); + buffer_append(&b, data, datalen); + + if (datafellows & SSH_OLD_SESSIONID) { + p = buffer_ptr(&b); + len = buffer_len(&b); + if ((session_id2 == NULL) || + (len < session_id2_len) || + (memcmp(p, session_id2, session_id2_len) != 0)) + fail++; + buffer_consume(&b, session_id2_len); + } else { + p = buffer_get_string(&b, &len); + if ((session_id2 == NULL) || + (len != session_id2_len) || + (memcmp(p, session_id2, session_id2_len) != 0)) + fail++; + xfree(p); + } + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + p = buffer_get_string(&b, NULL); + if (strcmp(authctxt->user, p) != 0) { + log("wrong user name passed to monitor: expected %s != %.100s", + authctxt->user, p); + fail++; + } + xfree(p); + buffer_skip_string(&b); + if (datafellows & SSH_BUG_PKAUTH) { + if (!buffer_get_char(&b)) + fail++; + } else { + p = buffer_get_string(&b, NULL); + if (strcmp("publickey", p) != 0) + fail++; + xfree(p); + if (!buffer_get_char(&b)) + fail++; + buffer_skip_string(&b); + } + buffer_skip_string(&b); + if (buffer_len(&b) != 0) + fail++; + buffer_free(&b); + return (fail == 0); +} + +static int +monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser, + u_char *chost) +{ + Buffer b; + u_char *p; + u_int len; + int fail = 0; + + buffer_init(&b); + buffer_append(&b, data, datalen); + + p = buffer_get_string(&b, &len); + if ((session_id2 == NULL) || + (len != session_id2_len) || + (memcmp(p, session_id2, session_id2_len) != 0)) + fail++; + xfree(p); + + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + p = buffer_get_string(&b, NULL); + if (strcmp(authctxt->user, p) != 0) { + log("wrong user name passed to monitor: expected %s != %.100s", + authctxt->user, p); + fail++; + } + xfree(p); + buffer_skip_string(&b); /* service */ + p = buffer_get_string(&b, NULL); + if (strcmp(p, "hostbased") != 0) + fail++; + xfree(p); + buffer_skip_string(&b); /* pkalg */ + buffer_skip_string(&b); /* pkblob */ + + /* verify client host, strip trailing dot if necessary */ + p = buffer_get_string(&b, NULL); + if (((len = strlen(p)) > 0) && p[len - 1] == '.') + p[len - 1] = '\0'; + if (strcmp(p, chost) != 0) + fail++; + xfree(p); + + /* verify client user */ + p = buffer_get_string(&b, NULL); + if (strcmp(p, cuser) != 0) + fail++; + xfree(p); + + if (buffer_len(&b) != 0) + fail++; + buffer_free(&b); + return (fail == 0); +} + +int +mm_answer_keyverify(int socket, Buffer *m) +{ + Key *key; + u_char *signature, *data, *blob; + u_int signaturelen, datalen, bloblen; + int verified = 0; + int valid_data = 0; + + blob = buffer_get_string(m, &bloblen); + signature = buffer_get_string(m, &signaturelen); + data = buffer_get_string(m, &datalen); + + if (hostbased_cuser == NULL || hostbased_chost == NULL || + !monitor_allowed_key(blob, bloblen)) + fatal("%s: bad key, not previously allowed", __func__); + + key = key_from_blob(blob, bloblen); + if (key == NULL) + fatal("%s: bad public key blob", __func__); + + switch (key_blobtype) { + case MM_USERKEY: + valid_data = monitor_valid_userblob(data, datalen); + break; + case MM_HOSTKEY: + valid_data = monitor_valid_hostbasedblob(data, datalen, + hostbased_cuser, hostbased_chost); + break; + default: + valid_data = 0; + break; + } + if (!valid_data) + fatal("%s: bad signature data blob", __func__); + + verified = key_verify(key, signature, signaturelen, data, datalen); + debug3("%s: key %p signature %s", + __func__, key, verified ? "verified" : "unverified"); + + key_free(key); + xfree(blob); + xfree(signature); + xfree(data); + + auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; + + monitor_reset_key_state(); + + buffer_clear(m); + buffer_put_int(m, verified); + mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m); + + return (verified); +} + +static void +mm_record_login(Session *s, struct passwd *pw) +{ + socklen_t fromlen; + struct sockaddr_storage from; + + /* + * Get IP address of client. If the connection is not a socket, let + * the address be 0.0.0.0. + */ + memset(&from, 0, sizeof(from)); + if (packet_connection_is_on_socket()) { + fromlen = sizeof(from); + if (getpeername(packet_get_connection_in(), + (struct sockaddr *) & from, &fromlen) < 0) { + debug("getpeername: %.100s", strerror(errno)); + fatal_cleanup(); + } + } + /* Record that there was a login on that tty from the remote host. */ + record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, + get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), + (struct sockaddr *)&from); +} + +static void +mm_session_close(Session *s) +{ + debug3("%s: session %d pid %d", __func__, s->self, s->pid); + if (s->ttyfd != -1) { + debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); + fatal_remove_cleanup(session_pty_cleanup2, (void *)s); + session_pty_cleanup2(s); + } + s->used = 0; +} + +int +mm_answer_pty(int socket, Buffer *m) +{ + extern struct monitor *pmonitor; + Session *s; + int res, fd0; + + debug3("%s entering", __func__); + + buffer_clear(m); + s = session_new(); + if (s == NULL) + goto error; + s->authctxt = authctxt; + s->pw = authctxt->pw; + s->pid = pmonitor->m_pid; + res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); + if (res == 0) + goto error; + fatal_add_cleanup(session_pty_cleanup2, (void *)s); + pty_setowner(authctxt->pw, s->tty); + + buffer_put_int(m, 1); + buffer_put_cstring(m, s->tty); + mm_request_send(socket, MONITOR_ANS_PTY, m); + + mm_send_fd(socket, s->ptyfd); + mm_send_fd(socket, s->ttyfd); + + /* We need to trick ttyslot */ + if (dup2(s->ttyfd, 0) == -1) + fatal("%s: dup2", __func__); + + mm_record_login(s, authctxt->pw); + + /* Now we can close the file descriptor again */ + close(0); + + /* make sure nothing uses fd 0 */ + if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) + fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); + if (fd0 != 0) + error("%s: fd0 %d != 0", __func__, fd0); + + /* slave is not needed */ + close(s->ttyfd); + s->ttyfd = s->ptyfd; + /* no need to dup() because nobody closes ptyfd */ + s->ptymaster = s->ptyfd; + + debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); + + return (0); + + error: + if (s != NULL) + mm_session_close(s); + buffer_put_int(m, 0); + mm_request_send(socket, MONITOR_ANS_PTY, m); + return (0); +} + +int +mm_answer_pty_cleanup(int socket, Buffer *m) +{ + Session *s; + char *tty; + + debug3("%s entering", __func__); + + tty = buffer_get_string(m, NULL); + if ((s = session_by_tty(tty)) != NULL) + mm_session_close(s); + buffer_clear(m); + xfree(tty); + return (0); +} + +int +mm_answer_sesskey(int socket, Buffer *m) +{ + BIGNUM *p; + int rsafail; + + /* Turn off permissions */ + monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); + + if ((p = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + + buffer_get_bignum2(m, p); + + rsafail = ssh1_session_key(p); + + buffer_clear(m); + buffer_put_int(m, rsafail); + buffer_put_bignum2(m, p); + + BN_clear_free(p); + + mm_request_send(socket, MONITOR_ANS_SESSKEY, m); + + /* Turn on permissions for sessid passing */ + monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); + + return (0); +} + +int +mm_answer_sessid(int socket, Buffer *m) +{ + int i; + + debug3("%s entering", __func__); + + if (buffer_len(m) != 16) + fatal("%s: bad ssh1 session id", __func__); + for (i = 0; i < 16; i++) + session_id[i] = buffer_get_char(m); + + /* Turn on permissions for getpwnam */ + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); + + return (0); +} + +int +mm_answer_rsa_keyallowed(int socket, Buffer *m) +{ + BIGNUM *client_n; + Key *key = NULL; + u_char *blob = NULL; + u_int blen = 0; + int allowed = 0; + + debug3("%s entering", __func__); + + if (options.rsa_authentication && authctxt->valid) { + if ((client_n = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, client_n); + allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); + BN_clear_free(client_n); + } + buffer_clear(m); + buffer_put_int(m, allowed); + + /* clear temporarily storage (used by generate challenge) */ + monitor_reset_key_state(); + + if (allowed && key != NULL) { + key->type = KEY_RSA; /* cheat for key_to_blob */ + if (key_to_blob(key, &blob, &blen) == 0) + fatal("%s: key_to_blob failed", __func__); + buffer_put_string(m, blob, blen); + + /* Save temporarily for comparison in verify */ + key_blob = blob; + key_bloblen = blen; + key_blobtype = MM_RSAUSERKEY; + key_free(key); + } + + mm_append_debug(m); + + mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); + monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); + return (0); +} + +int +mm_answer_rsa_challenge(int socket, Buffer *m) +{ + Key *key = NULL; + u_char *blob; + u_int blen; + + debug3("%s entering", __func__); + + if (!authctxt->valid) + fatal("%s: authctxt not valid", __func__); + blob = buffer_get_string(m, &blen); + if (!monitor_allowed_key(blob, blen)) + fatal("%s: bad key, not previously allowed", __func__); + if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) + fatal("%s: key type mismatch", __func__); + if ((key = key_from_blob(blob, blen)) == NULL) + fatal("%s: received bad key", __func__); + + if (ssh1_challenge) + BN_clear_free(ssh1_challenge); + ssh1_challenge = auth_rsa_generate_challenge(key); + + buffer_clear(m); + buffer_put_bignum2(m, ssh1_challenge); + + debug3("%s sending reply", __func__); + mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); + return (0); +} + +int +mm_answer_rsa_response(int socket, Buffer *m) +{ + Key *key = NULL; + u_char *blob, *response; + u_int blen, len; + int success; + + debug3("%s entering", __func__); + + if (!authctxt->valid) + fatal("%s: authctxt not valid", __func__); + if (ssh1_challenge == NULL) + fatal("%s: no ssh1_challenge", __func__); + + blob = buffer_get_string(m, &blen); + if (!monitor_allowed_key(blob, blen)) + fatal("%s: bad key, not previously allowed", __func__); + if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) + fatal("%s: key type mismatch: %d", __func__, key_blobtype); + if ((key = key_from_blob(blob, blen)) == NULL) + fatal("%s: received bad key", __func__); + response = buffer_get_string(m, &len); + if (len != 16) + fatal("%s: received bad response to challenge", __func__); + success = auth_rsa_verify_response(key, ssh1_challenge, response); + + key_free(key); + xfree(response); + + auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; + + /* reset state */ + BN_clear_free(ssh1_challenge); + ssh1_challenge = NULL; + monitor_reset_key_state(); + + buffer_clear(m); + buffer_put_int(m, success); + mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m); + + return (success); +} + +int +mm_answer_term(int socket, Buffer *req) +{ + extern struct monitor *pmonitor; + int res, status; + + debug3("%s: tearing down sessions", __func__); + + /* The child is terminating */ + session_destroy_all(&mm_session_close); + + while (waitpid(pmonitor->m_pid, &status, 0) == -1) + if (errno != EINTR) + exit(1); + + res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; + + /* Terminate process */ + exit (res); +} + +void +monitor_apply_keystate(struct monitor *pmonitor) +{ + if (compat20) { + set_newkeys(MODE_IN); + set_newkeys(MODE_OUT); + } else { + packet_set_protocol_flags(child_state.ssh1protoflags); + packet_set_encryption_key(child_state.ssh1key, + child_state.ssh1keylen, child_state.ssh1cipher); + xfree(child_state.ssh1key); + } + + /* for rc4 and other stateful ciphers */ + packet_set_keycontext(MODE_OUT, child_state.keyout); + xfree(child_state.keyout); + packet_set_keycontext(MODE_IN, child_state.keyin); + xfree(child_state.keyin); + + if (!compat20) { + packet_set_iv(MODE_OUT, child_state.ivout); + xfree(child_state.ivout); + packet_set_iv(MODE_IN, child_state.ivin); + xfree(child_state.ivin); + } + + memcpy(&incoming_stream, &child_state.incoming, + sizeof(incoming_stream)); + memcpy(&outgoing_stream, &child_state.outgoing, + sizeof(outgoing_stream)); + + /* Update with new address */ + if (options.compression) + mm_init_compression(pmonitor->m_zlib); + + /* Network I/O buffers */ + /* XXX inefficient for large buffers, need: buffer_init_from_string */ + buffer_clear(&input); + buffer_append(&input, child_state.input, child_state.ilen); + memset(child_state.input, 0, child_state.ilen); + xfree(child_state.input); + + buffer_clear(&output); + buffer_append(&output, child_state.output, child_state.olen); + memset(child_state.output, 0, child_state.olen); + xfree(child_state.output); +} + +static Kex * +mm_get_kex(Buffer *m) +{ + Kex *kex; + void *blob; + u_int bloblen; + + kex = xmalloc(sizeof(*kex)); + memset(kex, 0, sizeof(*kex)); + kex->session_id = buffer_get_string(m, &kex->session_id_len); + if ((session_id2 == NULL) || + (kex->session_id_len != session_id2_len) || + (memcmp(kex->session_id, session_id2, session_id2_len) != 0)) + fatal("mm_get_get: internal error: bad session id"); + kex->we_need = buffer_get_int(m); + kex->server = 1; + kex->hostkey_type = buffer_get_int(m); + kex->kex_type = buffer_get_int(m); + blob = buffer_get_string(m, &bloblen); + buffer_init(&kex->my); + buffer_append(&kex->my, blob, bloblen); + xfree(blob); + blob = buffer_get_string(m, &bloblen); + buffer_init(&kex->peer); + buffer_append(&kex->peer, blob, bloblen); + xfree(blob); + kex->done = 1; + kex->flags = buffer_get_int(m); + kex->client_version_string = buffer_get_string(m, NULL); + kex->server_version_string = buffer_get_string(m, NULL); + kex->load_host_key=&get_hostkey_by_type; + kex->host_key_index=&get_hostkey_index; + + return (kex); +} + +/* This function requries careful sanity checking */ + +void +mm_get_keystate(struct monitor *pmonitor) +{ + Buffer m; + u_char *blob, *p; + u_int bloblen, plen; + + debug3("%s: Waiting for new keys", __func__); + + buffer_init(&m); + mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); + if (!compat20) { + child_state.ssh1protoflags = buffer_get_int(&m); + child_state.ssh1cipher = buffer_get_int(&m); + child_state.ssh1key = buffer_get_string(&m, + &child_state.ssh1keylen); + child_state.ivout = buffer_get_string(&m, + &child_state.ivoutlen); + child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); + goto skip; + } else { + /* Get the Kex for rekeying */ + *pmonitor->m_pkex = mm_get_kex(&m); + } + + blob = buffer_get_string(&m, &bloblen); + current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); + xfree(blob); + + debug3("%s: Waiting for second key", __func__); + blob = buffer_get_string(&m, &bloblen); + current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); + xfree(blob); + + /* Now get sequence numbers for the packets */ + packet_set_seqnr(MODE_OUT, buffer_get_int(&m)); + packet_set_seqnr(MODE_IN, buffer_get_int(&m)); + + skip: + /* Get the key context */ + child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); + child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); + + debug3("%s: Getting compression state", __func__); + /* Get compression state */ + p = buffer_get_string(&m, &plen); + if (plen != sizeof(child_state.outgoing)) + fatal("%s: bad request size", __func__); + memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); + xfree(p); + + p = buffer_get_string(&m, &plen); + if (plen != sizeof(child_state.incoming)) + fatal("%s: bad request size", __func__); + memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); + xfree(p); + + /* Network I/O buffers */ + debug3("%s: Getting Network I/O buffers", __func__); + child_state.input = buffer_get_string(&m, &child_state.ilen); + child_state.output = buffer_get_string(&m, &child_state.olen); + + buffer_free(&m); +} + + +/* Allocation functions for zlib */ +void * +mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) +{ + int len = size * ncount; + void *address; + + if (len <= 0) + fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); + + address = mm_malloc(mm, len); + + return (address); +} + +void +mm_zfree(struct mm_master *mm, void *address) +{ + mm_free(mm, address); +} + +void +mm_init_compression(struct mm_master *mm) +{ + outgoing_stream.zalloc = (alloc_func)mm_zalloc; + outgoing_stream.zfree = (free_func)mm_zfree; + outgoing_stream.opaque = mm; + + incoming_stream.zalloc = (alloc_func)mm_zalloc; + incoming_stream.zfree = (free_func)mm_zfree; + incoming_stream.opaque = mm; +} + +/* XXX */ + +#define FD_CLOSEONEXEC(x) do { \ + if (fcntl(x, F_SETFD, 1) == -1) \ + fatal("fcntl(%d, F_SETFD)", x); \ +} while (0) + +static void +monitor_socketpair(int *pair) +{ +#ifdef HAVE_SOCKETPAIR + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) + fatal("%s: socketpair", __func__); +#else + fatal("%s: UsePrivilegeSeparation=yes not supported", + __func__); +#endif + FD_CLOSEONEXEC(pair[0]); + FD_CLOSEONEXEC(pair[1]); +} + +#define MM_MEMSIZE 65536 + +struct monitor * +monitor_init(void) +{ + struct monitor *mon; + int pair[2]; + + mon = xmalloc(sizeof(*mon)); + + monitor_socketpair(pair); + + mon->m_recvfd = pair[0]; + mon->m_sendfd = pair[1]; + + /* Used to share zlib space across processes */ + if (options.compression) { + mon->m_zback = mm_create(NULL, MM_MEMSIZE); + mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); + + /* Compression needs to share state across borders */ + mm_init_compression(mon->m_zlib); + } + + return mon; +} + +void +monitor_reinit(struct monitor *mon) +{ + int pair[2]; + + monitor_socketpair(pair); + + mon->m_recvfd = pair[0]; + mon->m_sendfd = pair[1]; +} Index: src/crypto/openssh/monitor.h =================================================================== RCS file: src/crypto/openssh/monitor.h diff -N src/crypto/openssh/monitor.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,87 @@ +/* $OpenBSD: monitor.h,v 1.6 2002/06/11 05:46:20 mpech Exp $ */ +/* $FreeBSD: src/crypto/openssh/monitor.h,v 1.2 2002/06/29 10:56:23 des Exp $ */ + +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MONITOR_H_ +#define _MONITOR_H_ + +enum monitor_reqtype { + MONITOR_REQ_MODULI, MONITOR_ANS_MODULI, + MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, + MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, + MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, + MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, + MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD, + MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY, + MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND, + MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY, + MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND, + MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED, + MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY, + MONITOR_REQ_KEYEXPORT, + MONITOR_REQ_PTY, MONITOR_ANS_PTY, + MONITOR_REQ_PTYCLEANUP, + MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY, + MONITOR_REQ_SESSID, + MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED, + MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE, + MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE, + MONITOR_REQ_PAM_START, + MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, + MONITOR_REQ_PAM_QUERY, MONITOR_ANS_PAM_QUERY, + MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND, + MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX, + MONITOR_REQ_TERM +}; + +struct mm_master; +struct monitor { + int m_recvfd; + int m_sendfd; + struct mm_master *m_zback; + struct mm_master *m_zlib; + struct Kex **m_pkex; + pid_t m_pid; +}; + +struct monitor *monitor_init(void); +void monitor_reinit(struct monitor *); +void monitor_sync(struct monitor *); + +struct Authctxt; +struct Authctxt *monitor_child_preauth(struct monitor *); +void monitor_child_postauth(struct monitor *); + +struct mon_table; +int monitor_read(struct monitor*, struct mon_table *, struct mon_table **); + +/* Prototypes for request sending and receiving */ +void mm_request_send(int, enum monitor_reqtype, Buffer *); +void mm_request_receive(int, Buffer *); +void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *); + +#endif /* _MONITOR_H_ */ Index: src/crypto/openssh/monitor_fdpass.c =================================================================== RCS file: src/crypto/openssh/monitor_fdpass.c diff -N src/crypto/openssh/monitor_fdpass.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor_fdpass.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,125 @@ +/* + * Copyright 2001 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: monitor_fdpass.c,v 1.3 2002/06/04 23:05:49 markus Exp $"); + +#include + +#include "log.h" +#include "monitor_fdpass.h" + +void +mm_send_fd(int socket, int fd) +{ +#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) + struct msghdr msg; + struct iovec vec; + char ch = '\0'; + int n; +#ifndef HAVE_ACCRIGHTS_IN_MSGHDR + char tmp[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; +#endif + + memset(&msg, 0, sizeof(msg)); +#ifdef HAVE_ACCRIGHTS_IN_MSGHDR + msg.msg_accrights = (caddr_t)&fd; + msg.msg_accrightslen = sizeof(fd); +#else + msg.msg_control = (caddr_t)tmp; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; +#endif + + vec.iov_base = &ch; + vec.iov_len = 1; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + + if ((n = sendmsg(socket, &msg, 0)) == -1) + fatal("%s: sendmsg(%d): %s", __func__, fd, + strerror(errno)); + if (n != 1) + fatal("%s: sendmsg: expected sent 1 got %d", + __func__, n); +#else + fatal("%s: UsePrivilegeSeparation=yes not supported", + __func__); +#endif +} + +int +mm_receive_fd(int socket) +{ +#if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) + struct msghdr msg; + struct iovec vec; + char ch; + int fd, n; +#ifndef HAVE_ACCRIGHTS_IN_MSGHDR + char tmp[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; +#endif + + memset(&msg, 0, sizeof(msg)); + vec.iov_base = &ch; + vec.iov_len = 1; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; +#ifdef HAVE_ACCRIGHTS_IN_MSGHDR + msg.msg_accrights = (caddr_t)&fd; + msg.msg_accrightslen = sizeof(fd); +#else + msg.msg_control = tmp; + msg.msg_controllen = sizeof(tmp); +#endif + + if ((n = recvmsg(socket, &msg, 0)) == -1) + fatal("%s: recvmsg: %s", __func__, strerror(errno)); + if (n != 1) + fatal("%s: recvmsg: expected received 1 got %d", + __func__, n); + +#ifdef HAVE_ACCRIGHTS_IN_MSGHDR + if (msg.msg_accrightslen != sizeof(fd)) + fatal("%s: no fd", __func__); +#else + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_type != SCM_RIGHTS) + fatal("%s: expected type %d got %d", __func__, + SCM_RIGHTS, cmsg->cmsg_type); + fd = (*(int *)CMSG_DATA(cmsg)); +#endif + return fd; +#else + fatal("%s: UsePrivilegeSeparation=yes not supported", + __func__); +#endif +} Index: src/crypto/openssh/monitor_fdpass.h =================================================================== RCS file: src/crypto/openssh/monitor_fdpass.h diff -N src/crypto/openssh/monitor_fdpass.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor_fdpass.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,34 @@ +/* $OpenBSD: monitor_fdpass.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */ + +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MM_FDPASS_H_ +#define _MM_FDPASS_H_ + +void mm_send_fd(int, int); +int mm_receive_fd(int); + +#endif /* _MM_FDPASS_H_ */ Index: src/crypto/openssh/monitor_mm.c =================================================================== RCS file: src/crypto/openssh/monitor_mm.c diff -N src/crypto/openssh/monitor_mm.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor_mm.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,342 @@ +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: monitor_mm.c,v 1.6 2002/06/04 23:05:49 markus Exp $"); + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#include "ssh.h" +#include "xmalloc.h" +#include "log.h" +#include "monitor_mm.h" + +static int +mm_compare(struct mm_share *a, struct mm_share *b) +{ + return ((char *)a->address - (char *)b->address); +} + +RB_GENERATE(mmtree, mm_share, next, mm_compare) + +static struct mm_share * +mm_make_entry(struct mm_master *mm, struct mmtree *head, + void *address, size_t size) +{ + struct mm_share *tmp, *tmp2; + + if (mm->mmalloc == NULL) + tmp = xmalloc(sizeof(struct mm_share)); + else + tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share)); + tmp->address = address; + tmp->size = size; + + tmp2 = RB_INSERT(mmtree, head, tmp); + if (tmp2 != NULL) + fatal("mm_make_entry(%p): double address %p->%p(%lu)", + mm, tmp2, address, (u_long)size); + + return (tmp); +} + +/* Creates a shared memory area of a certain size */ + +struct mm_master * +mm_create(struct mm_master *mmalloc, size_t size) +{ + void *address; + struct mm_master *mm; + + if (mmalloc == NULL) + mm = xmalloc(sizeof(struct mm_master)); + else + mm = mm_xmalloc(mmalloc, sizeof(struct mm_master)); + + /* + * If the memory map has a mm_master it can be completely + * shared including authentication between the child + * and the client. + */ + mm->mmalloc = mmalloc; + +#ifdef HAVE_MMAP_ANON_SHARED + address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, + -1, 0); + if (address == MAP_FAILED) + fatal("mmap(%lu): %s", (u_long)size, strerror(errno)); +#else + fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported", + __func__); +#endif + + mm->address = address; + mm->size = size; + + RB_INIT(&mm->rb_free); + RB_INIT(&mm->rb_allocated); + + mm_make_entry(mm, &mm->rb_free, address, size); + + return (mm); +} + +/* Frees either the allocated or the free list */ + +static void +mm_freelist(struct mm_master *mmalloc, struct mmtree *head) +{ + struct mm_share *mms, *next; + + for (mms = RB_ROOT(head); mms; mms = next) { + next = RB_NEXT(mmtree, head, mms); + RB_REMOVE(mmtree, head, mms); + if (mmalloc == NULL) + xfree(mms); + else + mm_free(mmalloc, mms); + } +} + +/* Destroys a memory mapped area */ + +void +mm_destroy(struct mm_master *mm) +{ + mm_freelist(mm->mmalloc, &mm->rb_free); + mm_freelist(mm->mmalloc, &mm->rb_allocated); + +#ifdef HAVE_MMAP_ANON_SHARED + if (munmap(mm->address, mm->size) == -1) + fatal("munmap(%p, %lu): %s", mm->address, (u_long)mm->size, + strerror(errno)); +#else + fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported", + __func__); +#endif + if (mm->mmalloc == NULL) + xfree(mm); + else + mm_free(mm->mmalloc, mm); +} + +void * +mm_xmalloc(struct mm_master *mm, size_t size) +{ + void *address; + + address = mm_malloc(mm, size); + if (address == NULL) + fatal("%s: mm_malloc(%lu)", __func__, (u_long)size); + return (address); +} + + +/* Allocates data from a memory mapped area */ + +void * +mm_malloc(struct mm_master *mm, size_t size) +{ + struct mm_share *mms, *tmp; + + if (size == 0) + fatal("mm_malloc: try to allocate 0 space"); + + size = ((size + MM_MINSIZE - 1) / MM_MINSIZE) * MM_MINSIZE; + + RB_FOREACH(mms, mmtree, &mm->rb_free) { + if (mms->size >= size) + break; + } + + if (mms == NULL) + return (NULL); + + /* Debug */ + memset(mms->address, 0xd0, size); + + tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size); + + /* Does not change order in RB tree */ + mms->size -= size; + mms->address = (u_char *)mms->address + size; + + if (mms->size == 0) { + RB_REMOVE(mmtree, &mm->rb_free, mms); + if (mm->mmalloc == NULL) + xfree(mms); + else + mm_free(mm->mmalloc, mms); + } + + return (tmp->address); +} + +/* Frees memory in a memory mapped area */ + +void +mm_free(struct mm_master *mm, void *address) +{ + struct mm_share *mms, *prev, tmp; + + tmp.address = address; + mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp); + if (mms == NULL) + fatal("mm_free(%p): can not find %p", mm, address); + + /* Debug */ + memset(mms->address, 0xd0, mms->size); + + /* Remove from allocated list and insert in free list */ + RB_REMOVE(mmtree, &mm->rb_allocated, mms); + if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL) + fatal("mm_free(%p): double address %p", mm, address); + + /* Find previous entry */ + prev = mms; + if (RB_LEFT(prev, next)) { + prev = RB_LEFT(prev, next); + while (RB_RIGHT(prev, next)) + prev = RB_RIGHT(prev, next); + } else { + if (RB_PARENT(prev, next) && + (prev == RB_RIGHT(RB_PARENT(prev, next), next))) + prev = RB_PARENT(prev, next); + else { + while (RB_PARENT(prev, next) && + (prev == RB_LEFT(RB_PARENT(prev, next), next))) + prev = RB_PARENT(prev, next); + prev = RB_PARENT(prev, next); + } + } + + /* Check if range does not overlap */ + if (prev != NULL && MM_ADDRESS_END(prev) > address) + fatal("mm_free: memory corruption: %p(%lu) > %p", + prev->address, (u_long)prev->size, address); + + /* See if we can merge backwards */ + if (prev != NULL && MM_ADDRESS_END(prev) == address) { + prev->size += mms->size; + RB_REMOVE(mmtree, &mm->rb_free, mms); + if (mm->mmalloc == NULL) + xfree(mms); + else + mm_free(mm->mmalloc, mms); + } else + prev = mms; + + if (prev == NULL) + return; + + /* Check if we can merge forwards */ + mms = RB_NEXT(mmtree, &mm->rb_free, prev); + if (mms == NULL) + return; + + if (MM_ADDRESS_END(prev) > mms->address) + fatal("mm_free: memory corruption: %p < %p(%lu)", + mms->address, prev->address, (u_long)prev->size); + if (MM_ADDRESS_END(prev) != mms->address) + return; + + prev->size += mms->size; + RB_REMOVE(mmtree, &mm->rb_free, mms); + + if (mm->mmalloc == NULL) + xfree(mms); + else + mm_free(mm->mmalloc, mms); +} + +static void +mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree, + struct mm_master *mm, struct mm_master *mmold) +{ + struct mm_master *mmalloc = mm->mmalloc; + struct mm_share *mms, *new; + + /* Sync free list */ + RB_FOREACH(mms, mmtree, oldtree) { + /* Check the values */ + mm_memvalid(mmold, mms, sizeof(struct mm_share)); + mm_memvalid(mm, mms->address, mms->size); + + new = mm_xmalloc(mmalloc, sizeof(struct mm_share)); + memcpy(new, mms, sizeof(struct mm_share)); + RB_INSERT(mmtree, newtree, new); + } +} + +void +mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc) +{ + struct mm_master *mm; + struct mm_master *mmalloc; + struct mm_master *mmold; + struct mmtree rb_free, rb_allocated; + + debug3("%s: Share sync", __func__); + + mm = *pmm; + mmold = mm->mmalloc; + mm_memvalid(mmold, mm, sizeof(*mm)); + + mmalloc = mm_create(NULL, mm->size); + mm = mm_xmalloc(mmalloc, sizeof(struct mm_master)); + memcpy(mm, *pmm, sizeof(struct mm_master)); + mm->mmalloc = mmalloc; + + rb_free = mm->rb_free; + rb_allocated = mm->rb_allocated; + + RB_INIT(&mm->rb_free); + RB_INIT(&mm->rb_allocated); + + mm_sync_list(&rb_free, &mm->rb_free, mm, mmold); + mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold); + + mm_destroy(mmold); + + *pmm = mm; + *pmmalloc = mmalloc; + + debug3("%s: Share sync end", __func__); +} + +void +mm_memvalid(struct mm_master *mm, void *address, size_t size) +{ + void *end = (u_char *)address + size; + + if (address < mm->address) + fatal("mm_memvalid: address too small: %p", address); + if (end < address) + fatal("mm_memvalid: end < address: %p < %p", end, address); + if (end > (void *)((u_char *)mm->address + mm->size)) + fatal("mm_memvalid: address too large: %p", address); +} Index: src/crypto/openssh/monitor_mm.h =================================================================== RCS file: src/crypto/openssh/monitor_mm.h diff -N src/crypto/openssh/monitor_mm.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor_mm.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,66 @@ +/* $OpenBSD: monitor_mm.h,v 1.2 2002/03/26 03:24:01 stevesk Exp $ */ + +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MM_H_ +#define _MM_H_ +#include "openbsd-compat/tree.h" + +struct mm_share { + RB_ENTRY(mm_share) next; + void *address; + size_t size; +}; + +struct mm_master { + RB_HEAD(mmtree, mm_share) rb_free; + struct mmtree rb_allocated; + void *address; + size_t size; + + struct mm_master *mmalloc; /* Used to completely share */ + + int write; /* used to writing to other party */ + int read; /* used for reading from other party */ +}; + +RB_PROTOTYPE(mmtree, mm_share, next, mm_compare) + +#define MM_MINSIZE 128 + +#define MM_ADDRESS_END(x) (void *)((u_char *)(x)->address + (x)->size) + +struct mm_master *mm_create(struct mm_master *, size_t); +void mm_destroy(struct mm_master *); + +void mm_share_sync(struct mm_master **, struct mm_master **); + +void *mm_malloc(struct mm_master *, size_t); +void *mm_xmalloc(struct mm_master *, size_t); +void mm_free(struct mm_master *, void *); + +void mm_memvalid(struct mm_master *, void *, size_t); +#endif /* _MM_H_ */ Index: src/crypto/openssh/monitor_wrap.c =================================================================== RCS file: src/crypto/openssh/monitor_wrap.c diff -N src/crypto/openssh/monitor_wrap.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor_wrap.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,1024 @@ +/* + * Copyright 2002 Niels Provos + * Copyright 2002 Markus Friedl + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +RCSID("$OpenBSD: monitor_wrap.c,v 1.11 2002/06/19 18:01:00 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/monitor_wrap.c,v 1.3 2002/06/29 10:56:23 des Exp $"); + +#include +#include + +#include "ssh.h" +#include "dh.h" +#include "kex.h" +#include "auth.h" +#include "buffer.h" +#include "bufaux.h" +#include "packet.h" +#include "mac.h" +#include "log.h" +#include "zlib.h" +#include "monitor.h" +#include "monitor_wrap.h" +#include "xmalloc.h" +#include "atomicio.h" +#include "monitor_fdpass.h" +#include "getput.h" + +#include "auth.h" +#include "channels.h" +#include "session.h" + +/* Imports */ +extern int compat20; +extern Newkeys *newkeys[]; +extern z_stream incoming_stream; +extern z_stream outgoing_stream; +extern struct monitor *pmonitor; +extern Buffer input, output; + +void +mm_request_send(int socket, enum monitor_reqtype type, Buffer *m) +{ + u_char buf[5]; + u_int mlen = buffer_len(m); + + debug3("%s entering: type %d", __func__, type); + + PUT_32BIT(buf, mlen + 1); + buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ + if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf)) + fatal("%s: write", __func__); + if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen) + fatal("%s: write", __func__); +} + +void +mm_request_receive(int socket, Buffer *m) +{ + u_char buf[4]; + ssize_t res; + u_int msg_len; + + debug3("%s entering", __func__); + + res = atomicio(read, socket, buf, sizeof(buf)); + if (res != sizeof(buf)) { + if (res == 0) + fatal_cleanup(); + fatal("%s: read: %ld", __func__, (long)res); + } + msg_len = GET_32BIT(buf); + if (msg_len > 256 * 1024) + fatal("%s: read: bad msg_len %d", __func__, msg_len); + buffer_clear(m); + buffer_append_space(m, msg_len); + res = atomicio(read, socket, buffer_ptr(m), msg_len); + if (res != msg_len) + fatal("%s: read: %ld != msg_len", __func__, (long)res); +} + +void +mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m) +{ + u_char rtype; + + debug3("%s entering: type %d", __func__, type); + + mm_request_receive(socket, m); + rtype = buffer_get_char(m); + if (rtype != type) + fatal("%s: read: rtype %d != type %d", __func__, + rtype, type); +} + +DH * +mm_choose_dh(int min, int nbits, int max) +{ + BIGNUM *p, *g; + int success = 0; + Buffer m; + + buffer_init(&m); + buffer_put_int(&m, min); + buffer_put_int(&m, nbits); + buffer_put_int(&m, max); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m); + + debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m); + + success = buffer_get_char(&m); + if (success == 0) + fatal("%s: MONITOR_ANS_MODULI failed", __func__); + + if ((p = BN_new()) == NULL) + fatal("%s: BN_new failed", __func__); + if ((g = BN_new()) == NULL) + fatal("%s: BN_new failed", __func__); + buffer_get_bignum2(&m, p); + buffer_get_bignum2(&m, g); + + debug3("%s: remaining %d", __func__, buffer_len(&m)); + buffer_free(&m); + + return (dh_new_group(g, p)); +} + +int +mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) +{ + Kex *kex = *pmonitor->m_pkex; + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + buffer_put_int(&m, kex->host_key_index(key)); + buffer_put_string(&m, data, datalen); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); + + debug3("%s: waiting for MONITOR_ANS_SIGN", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m); + *sigp = buffer_get_string(&m, lenp); + buffer_free(&m); + + return (0); +} + +struct passwd * +mm_getpwnamallow(const char *login) +{ + Buffer m; + struct passwd *pw; + u_int pwlen; + + debug3("%s entering", __func__); + + buffer_init(&m); + buffer_put_cstring(&m, login); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m); + + debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m); + + if (buffer_get_char(&m) == 0) { + buffer_free(&m); + return (NULL); + } + pw = buffer_get_string(&m, &pwlen); + if (pwlen != sizeof(struct passwd)) + fatal("%s: struct passwd size mismatch", __func__); + pw->pw_name = buffer_get_string(&m, NULL); + pw->pw_passwd = buffer_get_string(&m, NULL); + pw->pw_gecos = buffer_get_string(&m, NULL); +#ifdef HAVE_PW_CLASS_IN_PASSWD + pw->pw_class = buffer_get_string(&m, NULL); +#endif + pw->pw_dir = buffer_get_string(&m, NULL); + pw->pw_shell = buffer_get_string(&m, NULL); + buffer_free(&m); + + return (pw); +} + +char* mm_auth2_read_banner(void) +{ + Buffer m; + char *banner; + + debug3("%s entering", __func__); + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m); + buffer_clear(&m); + + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m); + banner = buffer_get_string(&m, NULL); + buffer_free(&m); + + return (banner); +} + +/* Inform the privileged process about service and style */ + +void +mm_inform_authserv(char *service, char *style) +{ + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + buffer_put_cstring(&m, service); + buffer_put_cstring(&m, style ? style : ""); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m); + + buffer_free(&m); +} + +/* Do the password authentication */ +int +mm_auth_password(Authctxt *authctxt, char *password) +{ + Buffer m; + int authenticated = 0; + + debug3("%s entering", __func__); + + buffer_init(&m); + buffer_put_cstring(&m, password); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m); + + debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m); + + authenticated = buffer_get_int(&m); + + buffer_free(&m); + + debug3("%s: user %sauthenticated", + __func__, authenticated ? "" : "not "); + return (authenticated); +} + +int +mm_user_key_allowed(struct passwd *pw, Key *key) +{ + return (mm_key_allowed(MM_USERKEY, NULL, NULL, key)); +} + +int +mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host, + Key *key) +{ + return (mm_key_allowed(MM_HOSTKEY, user, host, key)); +} + +int +mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user, + char *host, Key *key) +{ + int ret; + + key->type = KEY_RSA; /* XXX hack for key_to_blob */ + ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key); + key->type = KEY_RSA1; + return (ret); +} + +static void +mm_send_debug(Buffer *m) +{ + char *msg; + + while (buffer_len(m)) { + msg = buffer_get_string(m, NULL); + debug3("%s: Sending debug: %s", __func__, msg); + packet_send_debug("%s", msg); + xfree(msg); + } +} + +int +mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) +{ + Buffer m; + u_char *blob; + u_int len; + int allowed = 0; + + debug3("%s entering", __func__); + + /* Convert the key to a blob and the pass it over */ + if (!key_to_blob(key, &blob, &len)) + return (0); + + buffer_init(&m); + buffer_put_int(&m, type); + buffer_put_cstring(&m, user ? user : ""); + buffer_put_cstring(&m, host ? host : ""); + buffer_put_string(&m, blob, len); + xfree(blob); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m); + + debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m); + + allowed = buffer_get_int(&m); + + /* Send potential debug messages */ + mm_send_debug(&m); + + buffer_free(&m); + + return (allowed); +} + +/* + * This key verify needs to send the key type along, because the + * privileged parent makes the decision if the key is allowed + * for authentication. + */ + +int +mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) +{ + Buffer m; + u_char *blob; + u_int len; + int verified = 0; + + debug3("%s entering", __func__); + + /* Convert the key to a blob and the pass it over */ + if (!key_to_blob(key, &blob, &len)) + return (0); + + buffer_init(&m); + buffer_put_string(&m, blob, len); + buffer_put_string(&m, sig, siglen); + buffer_put_string(&m, data, datalen); + xfree(blob); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m); + + debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); + + verified = buffer_get_int(&m); + + buffer_free(&m); + + return (verified); +} + +/* Export key state after authentication */ +Newkeys * +mm_newkeys_from_blob(u_char *blob, int blen) +{ + Buffer b; + u_int len; + Newkeys *newkey = NULL; + Enc *enc; + Mac *mac; + Comp *comp; + + debug3("%s: %p(%d)", __func__, blob, blen); +#ifdef DEBUG_PK + dump_base64(stderr, blob, blen); +#endif + buffer_init(&b); + buffer_append(&b, blob, blen); + + newkey = xmalloc(sizeof(*newkey)); + enc = &newkey->enc; + mac = &newkey->mac; + comp = &newkey->comp; + + /* Enc structure */ + enc->name = buffer_get_string(&b, NULL); + buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); + enc->enabled = buffer_get_int(&b); + enc->block_size = buffer_get_int(&b); + enc->key = buffer_get_string(&b, &enc->key_len); + enc->iv = buffer_get_string(&b, &len); + if (len != enc->block_size) + fatal("%s: bad ivlen: expected %d != %d", __func__, + enc->block_size, len); + + if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) + fatal("%s: bad cipher name %s or pointer %p", __func__, + enc->name, enc->cipher); + + /* Mac structure */ + mac->name = buffer_get_string(&b, NULL); + if (mac->name == NULL || mac_init(mac, mac->name) == -1) + fatal("%s: can not init mac %s", __func__, mac->name); + mac->enabled = buffer_get_int(&b); + mac->key = buffer_get_string(&b, &len); + if (len > mac->key_len) + fatal("%s: bad mac key length: %d > %d", __func__, len, + mac->key_len); + mac->key_len = len; + + /* Comp structure */ + comp->type = buffer_get_int(&b); + comp->enabled = buffer_get_int(&b); + comp->name = buffer_get_string(&b, NULL); + + len = buffer_len(&b); + if (len != 0) + error("newkeys_from_blob: remaining bytes in blob %d", len); + buffer_free(&b); + return (newkey); +} + +int +mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) +{ + Buffer b; + int len; + u_char *buf; + Enc *enc; + Mac *mac; + Comp *comp; + Newkeys *newkey = newkeys[mode]; + + debug3("%s: converting %p", __func__, newkey); + + if (newkey == NULL) { + error("%s: newkey == NULL", __func__); + return 0; + } + enc = &newkey->enc; + mac = &newkey->mac; + comp = &newkey->comp; + + buffer_init(&b); + /* Enc structure */ + buffer_put_cstring(&b, enc->name); + /* The cipher struct is constant and shared, you export pointer */ + buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); + buffer_put_int(&b, enc->enabled); + buffer_put_int(&b, enc->block_size); + buffer_put_string(&b, enc->key, enc->key_len); + packet_get_keyiv(mode, enc->iv, enc->block_size); + buffer_put_string(&b, enc->iv, enc->block_size); + + /* Mac structure */ + buffer_put_cstring(&b, mac->name); + buffer_put_int(&b, mac->enabled); + buffer_put_string(&b, mac->key, mac->key_len); + + /* Comp structure */ + buffer_put_int(&b, comp->type); + buffer_put_int(&b, comp->enabled); + buffer_put_cstring(&b, comp->name); + + len = buffer_len(&b); + buf = xmalloc(len); + memcpy(buf, buffer_ptr(&b), len); + memset(buffer_ptr(&b), 0, len); + buffer_free(&b); + if (lenp != NULL) + *lenp = len; + if (blobp != NULL) + *blobp = buf; + return len; +} + +static void +mm_send_kex(Buffer *m, Kex *kex) +{ + buffer_put_string(m, kex->session_id, kex->session_id_len); + buffer_put_int(m, kex->we_need); + buffer_put_int(m, kex->hostkey_type); + buffer_put_int(m, kex->kex_type); + buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); + buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); + buffer_put_int(m, kex->flags); + buffer_put_cstring(m, kex->client_version_string); + buffer_put_cstring(m, kex->server_version_string); +} + +void +mm_send_keystate(struct monitor *pmonitor) +{ + Buffer m; + u_char *blob, *p; + u_int bloblen, plen; + + buffer_init(&m); + + if (!compat20) { + u_char iv[24]; + u_char *key; + u_int ivlen, keylen; + + buffer_put_int(&m, packet_get_protocol_flags()); + + buffer_put_int(&m, packet_get_ssh1_cipher()); + + debug3("%s: Sending ssh1 KEY+IV", __func__); + keylen = packet_get_encryption_key(NULL); + key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ + keylen = packet_get_encryption_key(key); + buffer_put_string(&m, key, keylen); + memset(key, 0, keylen); + xfree(key); + + ivlen = packet_get_keyiv_len(MODE_OUT); + packet_get_keyiv(MODE_OUT, iv, ivlen); + buffer_put_string(&m, iv, ivlen); + ivlen = packet_get_keyiv_len(MODE_OUT); + packet_get_keyiv(MODE_IN, iv, ivlen); + buffer_put_string(&m, iv, ivlen); + goto skip; + } else { + /* Kex for rekeying */ + mm_send_kex(&m, *pmonitor->m_pkex); + } + + debug3("%s: Sending new keys: %p %p", + __func__, newkeys[MODE_OUT], newkeys[MODE_IN]); + + /* Keys from Kex */ + if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) + fatal("%s: conversion of newkeys failed", __func__); + + buffer_put_string(&m, blob, bloblen); + xfree(blob); + + if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) + fatal("%s: conversion of newkeys failed", __func__); + + buffer_put_string(&m, blob, bloblen); + xfree(blob); + + buffer_put_int(&m, packet_get_seqnr(MODE_OUT)); + buffer_put_int(&m, packet_get_seqnr(MODE_IN)); + + debug3("%s: New keys have been sent", __func__); + skip: + /* More key context */ + plen = packet_get_keycontext(MODE_OUT, NULL); + p = xmalloc(plen+1); + packet_get_keycontext(MODE_OUT, p); + buffer_put_string(&m, p, plen); + xfree(p); + + plen = packet_get_keycontext(MODE_IN, NULL); + p = xmalloc(plen+1); + packet_get_keycontext(MODE_IN, p); + buffer_put_string(&m, p, plen); + xfree(p); + + /* Compression state */ + debug3("%s: Sending compression state", __func__); + buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); + buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); + + /* Network I/O buffers */ + buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input)); + buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output)); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); + debug3("%s: Finished sending state", __func__); + + buffer_free(&m); +} + +int +mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) +{ + Buffer m; + u_char *p; + int success = 0; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m); + + debug3("%s: waiting for MONITOR_ANS_PTY", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m); + + success = buffer_get_int(&m); + if (success == 0) { + debug3("%s: pty alloc failed", __func__); + buffer_free(&m); + return (0); + } + p = buffer_get_string(&m, NULL); + buffer_free(&m); + + strlcpy(namebuf, p, namebuflen); /* Possible truncation */ + xfree(p); + + *ptyfd = mm_receive_fd(pmonitor->m_recvfd); + *ttyfd = mm_receive_fd(pmonitor->m_recvfd); + + /* Success */ + return (1); +} + +void +mm_session_pty_cleanup2(void *session) +{ + Session *s = session; + Buffer m; + + if (s->ttyfd == -1) + return; + buffer_init(&m); + buffer_put_cstring(&m, s->tty); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m); + buffer_free(&m); + + /* closed dup'ed master */ + if (close(s->ptymaster) < 0) + error("close(s->ptymaster): %s", strerror(errno)); + + /* unlink pty from session */ + s->ttyfd = -1; +} + +#ifdef USE_PAM +void +mm_start_pam(char *user) +{ + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + buffer_put_cstring(&m, user); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m); + + buffer_free(&m); +} + +void * +mm_pam_init_ctx(Authctxt *authctxt) +{ + Buffer m; + int success; + + debug3("%s", __func__); + buffer_init(&m); + buffer_put_cstring(&m, authctxt->user); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m); + debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m); + success = buffer_get_int(&m); + if (success == 0) { + debug3("%s: pam_init_ctx failed", __func__); + buffer_free(&m); + return (NULL); + } + buffer_free(&m); + return (authctxt); +} + +int +mm_pam_query(void *ctx, char **name, char **info, + u_int *num, char ***prompts, u_int **echo_on) +{ + Buffer m; + int i, ret; + + debug3("%s", __func__); + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m); + debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m); + ret = buffer_get_int(&m); + debug3("%s: pam_query returned %d", __func__, ret); + *name = buffer_get_string(&m, NULL); + *info = buffer_get_string(&m, NULL); + *num = buffer_get_int(&m); + *prompts = xmalloc((*num + 1) * sizeof(char *)); + *echo_on = xmalloc((*num + 1) * sizeof(u_int)); + for (i = 0; i < *num; ++i) { + (*prompts)[i] = buffer_get_string(&m, NULL); + (*echo_on)[i] = buffer_get_int(&m); + } + buffer_free(&m); + return (ret); +} + +int +mm_pam_respond(void *ctx, u_int num, char **resp) +{ + Buffer m; + int i, ret; + + debug3("%s", __func__); + buffer_init(&m); + buffer_put_int(&m, num); + for (i = 0; i < num; ++i) + buffer_put_cstring(&m, resp[i]); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m); + debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m); + ret = buffer_get_int(&m); + debug3("%s: pam_respond returned %d", __func__, ret); + buffer_free(&m); + return (ret); +} + +void +mm_pam_free_ctx(void *ctxtp) +{ + Buffer m; + + debug3("%s", __func__); + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m); + debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m); + buffer_free(&m); +} +#endif /* USE_PAM */ + +/* Request process termination */ + +void +mm_terminate(void) +{ + Buffer m; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m); + buffer_free(&m); +} + +int +mm_ssh1_session_key(BIGNUM *num) +{ + int rsafail; + Buffer m; + + buffer_init(&m); + buffer_put_bignum2(&m, num); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); + + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); + + rsafail = buffer_get_int(&m); + buffer_get_bignum2(&m, num); + + buffer_free(&m); + + return (rsafail); +} + +static void +mm_chall_setup(char **name, char **infotxt, u_int *numprompts, + char ***prompts, u_int **echo_on) +{ + *name = xstrdup(""); + *infotxt = xstrdup(""); + *numprompts = 1; + *prompts = xmalloc(*numprompts * sizeof(char*)); + *echo_on = xmalloc(*numprompts * sizeof(u_int)); + (*echo_on)[0] = 0; +} + +int +mm_bsdauth_query(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on) +{ + Buffer m; + int res; + char *challenge; + + debug3("%s: entering", __func__); + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m); + + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY, + &m); + res = buffer_get_int(&m); + if (res == -1) { + debug3("%s: no challenge", __func__); + buffer_free(&m); + return (-1); + } + + /* Get the challenge, and format the response */ + challenge = buffer_get_string(&m, NULL); + buffer_free(&m); + + mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); + (*prompts)[0] = challenge; + + debug3("%s: received challenge: %s", __func__, challenge); + + return (0); +} + +int +mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) +{ + Buffer m; + int authok; + + debug3("%s: entering", __func__); + if (numresponses != 1) + return (-1); + + buffer_init(&m); + buffer_put_cstring(&m, responses[0]); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m); + + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_BSDAUTHRESPOND, &m); + + authok = buffer_get_int(&m); + buffer_free(&m); + + return ((authok == 0) ? -1 : 0); +} + +#ifdef SKEY +int +mm_skey_query(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on) +{ + Buffer m; + int len, res; + char *p, *challenge; + + debug3("%s: entering", __func__); + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m); + + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY, + &m); + res = buffer_get_int(&m); + if (res == -1) { + debug3("%s: no challenge", __func__); + buffer_free(&m); + return (-1); + } + + /* Get the challenge, and format the response */ + challenge = buffer_get_string(&m, NULL); + buffer_free(&m); + + debug3("%s: received challenge: %s", __func__, challenge); + + mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); + + len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; + p = xmalloc(len); + strlcpy(p, challenge, len); + strlcat(p, SKEY_PROMPT, len); + (*prompts)[0] = p; + xfree(challenge); + + return (0); +} + +int +mm_skey_respond(void *ctx, u_int numresponses, char **responses) +{ + Buffer m; + int authok; + + debug3("%s: entering", __func__); + if (numresponses != 1) + return (-1); + + buffer_init(&m); + buffer_put_cstring(&m, responses[0]); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m); + + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_SKEYRESPOND, &m); + + authok = buffer_get_int(&m); + buffer_free(&m); + + return ((authok == 0) ? -1 : 0); +} +#endif + +void +mm_ssh1_session_id(u_char session_id[16]) +{ + Buffer m; + int i; + + debug3("%s entering", __func__); + + buffer_init(&m); + for (i = 0; i < 16; i++) + buffer_put_char(&m, session_id[i]); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m); + buffer_free(&m); +} + +int +mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) +{ + Buffer m; + Key *key; + u_char *blob; + u_int blen; + int allowed = 0; + + debug3("%s entering", __func__); + + buffer_init(&m); + buffer_put_bignum2(&m, client_n); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m); + + allowed = buffer_get_int(&m); + + if (allowed && rkey != NULL) { + blob = buffer_get_string(&m, &blen); + if ((key = key_from_blob(blob, blen)) == NULL) + fatal("%s: key_from_blob failed", __func__); + *rkey = key; + xfree(blob); + } + mm_send_debug(&m); + buffer_free(&m); + + return (allowed); +} + +BIGNUM * +mm_auth_rsa_generate_challenge(Key *key) +{ + Buffer m; + BIGNUM *challenge; + u_char *blob; + u_int blen; + + debug3("%s entering", __func__); + + if ((challenge = BN_new()) == NULL) + fatal("%s: BN_new failed", __func__); + + key->type = KEY_RSA; /* XXX cheat for key_to_blob */ + if (key_to_blob(key, &blob, &blen) == 0) + fatal("%s: key_to_blob failed", __func__); + key->type = KEY_RSA1; + + buffer_init(&m); + buffer_put_string(&m, blob, blen); + xfree(blob); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); + + buffer_get_bignum2(&m, challenge); + buffer_free(&m); + + return (challenge); +} + +int +mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) +{ + Buffer m; + u_char *blob; + u_int blen; + int success = 0; + + debug3("%s entering", __func__); + + key->type = KEY_RSA; /* XXX cheat for key_to_blob */ + if (key_to_blob(key, &blob, &blen) == 0) + fatal("%s: key_to_blob failed", __func__); + key->type = KEY_RSA1; + + buffer_init(&m); + buffer_put_string(&m, blob, blen); + buffer_put_string(&m, response, 16); + xfree(blob); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m); + + success = buffer_get_int(&m); + buffer_free(&m); + + return (success); +} Index: src/crypto/openssh/monitor_wrap.h =================================================================== RCS file: src/crypto/openssh/monitor_wrap.h diff -N src/crypto/openssh/monitor_wrap.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/monitor_wrap.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,97 @@ +/* $OpenBSD: monitor_wrap.h,v 1.5 2002/05/12 23:53:45 djm Exp $ */ +/* $FreeBSD: src/crypto/openssh/monitor_wrap.h,v 1.2 2002/06/29 10:56:23 des Exp $ */ + +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MM_WRAP_H_ +#define _MM_WRAP_H_ +#include "key.h" +#include "buffer.h" + +extern int use_privsep; +#define PRIVSEP(x) (use_privsep ? mm_##x : x) + +enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY}; + +struct monitor; +struct mm_master; +struct passwd; +struct Authctxt; + +DH *mm_choose_dh(int, int, int); +int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); +void mm_inform_authserv(char *, char *); +struct passwd *mm_getpwnamallow(const char *); +char* mm_auth2_read_banner(void); +int mm_auth_password(struct Authctxt *, char *); +int mm_key_allowed(enum mm_keytype, char *, char *, Key *); +int mm_user_key_allowed(struct passwd *, Key *); +int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *); +int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); +int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); +int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); +int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *); +BIGNUM *mm_auth_rsa_generate_challenge(Key *); + +#ifdef USE_PAM +void mm_start_pam(char *); +void *mm_pam_init_ctx(struct Authctxt *); +int mm_pam_query(void *, char **, char **, u_int *, char ***, u_int **); +int mm_pam_respond(void *, u_int, char **); +void mm_pam_free_ctx(void *); +#endif + +void mm_terminate(void); +int mm_pty_allocate(int *, int *, char *, int); +void mm_session_pty_cleanup2(void *); + +/* SSHv1 interfaces */ +void mm_ssh1_session_id(u_char *); +int mm_ssh1_session_key(BIGNUM *); + +/* Key export functions */ +struct Newkeys *mm_newkeys_from_blob(u_char *, int); +int mm_newkeys_to_blob(int, u_char **, u_int *); + +void monitor_apply_keystate(struct monitor *); +void mm_get_keystate(struct monitor *); +void mm_send_keystate(struct monitor*); + +/* bsdauth */ +int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); +int mm_bsdauth_respond(void *, u_int, char **); + +/* skey */ +int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); +int mm_skey_respond(void *, u_int, char **); + +/* zlib allocation hooks */ + +void *mm_zalloc(struct mm_master *, u_int, u_int); +void mm_zfree(struct mm_master *, void *); +void mm_init_compression(struct mm_master *); + +#endif /* _MM_H_ */ Index: src/crypto/openssh/mpaux.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/mpaux.c,v retrieving revision 1.2.2.3 diff -u -u -r1.2.2.3 mpaux.c --- src/crypto/openssh/mpaux.c 28 Sep 2001 01:33:34 -0000 1.2.2.3 +++ src/crypto/openssh/mpaux.c 30 Jun 2002 11:37:59 -0000 @@ -14,7 +14,6 @@ #include "includes.h" RCSID("$OpenBSD: mpaux.c,v 1.16 2001/02/08 19:30:52 itojun Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/mpaux.c,v 1.2.2.3 2001/09/28 01:33:34 green Exp $"); #include #include "getput.h" Index: src/crypto/openssh/mpaux.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/mpaux.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 mpaux.h --- src/crypto/openssh/mpaux.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/mpaux.h 30 Jun 2002 11:37:59 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: mpaux.h,v 1.12 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,20 +14,9 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: mpaux.h,v 1.9 2000/12/19 23:17:57 markus Exp $"); */ - #ifndef MPAUX_H #define MPAUX_H -/* - * 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(u_char session_id[16], - u_char cookie[8], - BIGNUM * host_key_n, - BIGNUM * session_key_n); +void compute_session_id(u_char[16], u_char[8], BIGNUM *, BIGNUM *); #endif /* MPAUX_H */ Index: src/crypto/openssh/msg.c =================================================================== RCS file: src/crypto/openssh/msg.c diff -N src/crypto/openssh/msg.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/msg.c 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "includes.h" +RCSID("$OpenBSD: msg.c,v 1.3 2002/06/24 15:49:22 itojun Exp $"); + +#include "buffer.h" +#include "getput.h" +#include "log.h" +#include "atomicio.h" +#include "msg.h" + +void +msg_send(int fd, u_char type, Buffer *m) +{ + u_char buf[5]; + u_int mlen = buffer_len(m); + + debug3("msg_send: type %u", (unsigned int)type & 0xff); + + PUT_32BIT(buf, mlen + 1); + buf[4] = type; /* 1st byte of payload is mesg-type */ + if (atomicio(write, fd, buf, sizeof(buf)) != sizeof(buf)) + fatal("msg_send: write"); + if (atomicio(write, fd, buffer_ptr(m), mlen) != mlen) + fatal("msg_send: write"); +} + +int +msg_recv(int fd, Buffer *m) +{ + u_char buf[4]; + ssize_t res; + u_int msg_len; + + debug3("msg_recv entering"); + + res = atomicio(read, fd, buf, sizeof(buf)); + if (res != sizeof(buf)) { + if (res == 0) + return -1; + fatal("msg_recv: read: header %ld", (long)res); + } + msg_len = GET_32BIT(buf); + if (msg_len > 256 * 1024) + fatal("msg_recv: read: bad msg_len %d", msg_len); + buffer_clear(m); + buffer_append_space(m, msg_len); + res = atomicio(read, fd, buffer_ptr(m), msg_len); + if (res != msg_len) + fatal("msg_recv: read: %ld != msg_len", (long)res); + return 0; +} Index: src/crypto/openssh/msg.h =================================================================== RCS file: src/crypto/openssh/msg.h diff -N src/crypto/openssh/msg.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/msg.h 30 Jun 2002 11:37:59 -0000 @@ -0,0 +1,31 @@ +/* $OpenBSD: msg.h,v 1.1 2002/05/23 19:24:30 markus Exp $ */ +/* + * Copyright (c) 2002 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SSH_MSG_H +#define SSH_MSG_H + +void msg_send(int, u_char, Buffer *); +int msg_recv(int, Buffer *); + +#endif Index: src/crypto/openssh/myproposal.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/myproposal.h,v retrieving revision 1.1.1.2.2.4 diff -u -u -r1.1.1.2.2.4 myproposal.h --- src/crypto/openssh/myproposal.h 28 Sep 2001 01:33:34 -0000 1.1.1.2.2.4 +++ src/crypto/openssh/myproposal.h 30 Jun 2002 11:37:59 -0000 @@ -1,4 +1,5 @@ -/* $OpenBSD: myproposal.h,v 1.12 2001/03/05 15:56:16 deraadt Exp $ */ +/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */ +/* $FreeBSD: src/crypto/openssh/myproposal.h,v 1.5 2002/06/29 10:51:56 des Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -24,12 +25,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1" -#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" +#define KEX_DEFAULT_PK_ALG "ssh-dss,ssh-rsa" #define KEX_DEFAULT_ENCRYPT \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \ - "aes192-cbc,aes256-cbc," \ - "rijndael128-cbc,rijndael192-cbc,rijndael256-cbc," \ - "rijndael-cbc@lysator.liu.se" + "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" #define KEX_DEFAULT_MAC \ "hmac-md5,hmac-sha1,hmac-ripemd160," \ "hmac-ripemd160@openssh.com," \ Index: src/crypto/openssh/nchan.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/nchan.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 nchan.c --- src/crypto/openssh/nchan.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/nchan.c 30 Jun 2002 11:37:59 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Markus Friedl. All rights reserved. + * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,40 +23,79 @@ */ #include "includes.h" -RCSID("$OpenBSD: nchan.c,v 1.23 2001/02/28 08:54:55 markus Exp $"); +RCSID("$OpenBSD: nchan.c,v 1.47 2002/06/19 00:27:55 deraadt Exp $"); #include "ssh1.h" #include "ssh2.h" #include "buffer.h" #include "packet.h" #include "channels.h" -#include "nchan.h" #include "compat.h" #include "log.h" +/* + * SSH Protocol 1.5 aka New Channel Protocol + * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored. + * Written by Markus Friedl in October 1999 + * + * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the + * tear down of channels: + * + * 1.3: strict request-ack-protocol: + * CLOSE -> + * <- CLOSE_CONFIRM + * + * 1.5: uses variations of: + * IEOF -> + * <- OCLOSE + * <- IEOF + * OCLOSE -> + * i.e. both sides have to close the channel + * + * 2.0: the EOF messages are optional + * + * See the debugging output from 'ssh -v' and 'sshd -d' of + * ssh-1.2.27 as an example. + * + */ + /* functions manipulating channel states */ /* * EVENTS update channel input/output states execute ACTIONS */ -/* events concerning the INPUT from socket for channel (istate) */ -chan_event_fn *chan_rcvd_oclose = NULL; -chan_event_fn *chan_read_failed = NULL; -chan_event_fn *chan_ibuf_empty = NULL; -/* events concerning the OUTPUT from channel for socket (ostate) */ -chan_event_fn *chan_rcvd_ieof = NULL; -chan_event_fn *chan_write_failed = NULL; -chan_event_fn *chan_obuf_empty = NULL; /* * ACTIONS: should never update the channel states */ -static void chan_send_ieof1(Channel *c); -static void chan_send_oclose1(Channel *c); -static void chan_send_close2(Channel *c); -static void chan_send_eof2(Channel *c); +static void chan_send_ieof1(Channel *); +static void chan_send_oclose1(Channel *); +static void chan_send_close2(Channel *); +static void chan_send_eof2(Channel *); /* helper */ -static void chan_shutdown_write(Channel *c); -static void chan_shutdown_read(Channel *c); +static void chan_shutdown_write(Channel *); +static void chan_shutdown_read(Channel *); + +static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; +static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; + +static void +chan_set_istate(Channel *c, u_int next) +{ + if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED) + fatal("chan_set_istate: bad state %d -> %d", c->istate, next); + debug("channel %d: input %s -> %s", c->self, istates[c->istate], + istates[next]); + c->istate = next; +} +static void +chan_set_ostate(Channel *c, u_int next) +{ + if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED) + fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next); + debug("channel %d: output %s -> %s", c->self, ostates[c->ostate], + ostates[next]); + c->ostate = next; +} /* * SSH1 specific implementation of event functions @@ -68,64 +107,61 @@ debug("channel %d: rcvd oclose", c->self); switch (c->istate) { case CHAN_INPUT_WAIT_OCLOSE: - debug("channel %d: input wait_oclose -> closed", c->self); - c->istate = CHAN_INPUT_CLOSED; + chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_OPEN: - debug("channel %d: input open -> closed", c->self); chan_shutdown_read(c); chan_send_ieof1(c); - c->istate = CHAN_INPUT_CLOSED; + chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_WAIT_DRAIN: /* both local read_failed and remote write_failed */ - log("channel %d: input drain -> closed", c->self); chan_send_ieof1(c); - c->istate = CHAN_INPUT_CLOSED; + chan_set_istate(c, CHAN_INPUT_CLOSED); break; default: - error("channel %d: protocol error: chan_rcvd_oclose for istate %d", + error("channel %d: protocol error: rcvd_oclose for istate %d", c->self, c->istate); return; } } -static void -chan_read_failed_12(Channel *c) +void +chan_read_failed(Channel *c) { debug("channel %d: read failed", c->self); switch (c->istate) { case CHAN_INPUT_OPEN: - debug("channel %d: input open -> drain", c->self); chan_shutdown_read(c); - c->istate = CHAN_INPUT_WAIT_DRAIN; - if (buffer_len(&c->input) == 0) { - debug("channel %d: input: no drain shortcut", c->self); - chan_ibuf_empty(c); - } + chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); break; default: - error("channel %d: internal error: we do not read, but chan_read_failed for istate %d", + error("channel %d: chan_read_failed for istate %d", c->self, c->istate); break; } } -static void -chan_ibuf_empty1(Channel *c) +void +chan_ibuf_empty(Channel *c) { debug("channel %d: ibuf empty", c->self); if (buffer_len(&c->input)) { - error("channel %d: internal error: chan_ibuf_empty for non empty buffer", + error("channel %d: chan_ibuf_empty for non empty buffer", c->self); return; } switch (c->istate) { case CHAN_INPUT_WAIT_DRAIN: - debug("channel %d: input drain -> wait_oclose", c->self); - chan_send_ieof1(c); - c->istate = CHAN_INPUT_WAIT_OCLOSE; + if (compat20) { + if (!(c->flags & CHAN_CLOSE_SENT)) + chan_send_eof2(c); + chan_set_istate(c, CHAN_INPUT_CLOSED); + } else { + chan_send_ieof1(c); + chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE); + } break; default: - error("channel %d: internal error: chan_ibuf_empty for istate %d", + error("channel %d: chan_ibuf_empty for istate %d", c->self, c->istate); break; } @@ -134,36 +170,15 @@ chan_rcvd_ieof1(Channel *c) { debug("channel %d: rcvd ieof", c->self); - if (c->type != SSH_CHANNEL_OPEN) { - debug("channel %d: non-open", c->self); - if (c->istate == CHAN_INPUT_OPEN) { - debug("channel %d: non-open: input open -> wait_oclose", c->self); - chan_shutdown_read(c); - chan_send_ieof1(c); - c->istate = CHAN_INPUT_WAIT_OCLOSE; - } else { - error("channel %d: istate %d != open", c->self, c->istate); - } - if (c->ostate == CHAN_OUTPUT_OPEN) { - debug("channel %d: non-open: output open -> closed", c->self); - chan_send_oclose1(c); - c->ostate = CHAN_OUTPUT_CLOSED; - } else { - error("channel %d: ostate %d != open", c->self, c->ostate); - } - return; - } switch (c->ostate) { case CHAN_OUTPUT_OPEN: - debug("channel %d: output open -> drain", c->self); - c->ostate = CHAN_OUTPUT_WAIT_DRAIN; + chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); break; case CHAN_OUTPUT_WAIT_IEOF: - debug("channel %d: output wait_ieof -> closed", c->self); - c->ostate = CHAN_OUTPUT_CLOSED; + chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: - error("channel %d: protocol error: chan_rcvd_ieof for ostate %d", + error("channel %d: protocol error: rcvd_ieof for ostate %d", c->self, c->ostate); break; } @@ -174,38 +189,39 @@ debug("channel %d: write failed", c->self); switch (c->ostate) { case CHAN_OUTPUT_OPEN: - debug("channel %d: output open -> wait_ieof", c->self); + chan_shutdown_write(c); chan_send_oclose1(c); - c->ostate = CHAN_OUTPUT_WAIT_IEOF; + chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF); break; case CHAN_OUTPUT_WAIT_DRAIN: - debug("channel %d: output wait_drain -> closed", c->self); + chan_shutdown_write(c); chan_send_oclose1(c); - c->ostate = CHAN_OUTPUT_CLOSED; + chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: - error("channel %d: internal error: chan_write_failed for ostate %d", + error("channel %d: chan_write_failed for ostate %d", c->self, c->ostate); break; } } -static void -chan_obuf_empty1(Channel *c) +void +chan_obuf_empty(Channel *c) { debug("channel %d: obuf empty", c->self); if (buffer_len(&c->output)) { - error("channel %d: internal error: chan_obuf_empty for non empty buffer", + error("channel %d: chan_obuf_empty for non empty buffer", c->self); return; } switch (c->ostate) { case CHAN_OUTPUT_WAIT_DRAIN: - debug("channel %d: output drain -> closed", c->self); - chan_send_oclose1(c); - c->ostate = CHAN_OUTPUT_CLOSED; + chan_shutdown_write(c); + if (!compat20) + chan_send_oclose1(c); + chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: - error("channel %d: internal error: chan_obuf_empty for ostate %d", + error("channel %d: internal error: obuf_empty for ostate %d", c->self, c->ostate); break; } @@ -222,7 +238,7 @@ packet_send(); break; default: - error("channel %d: internal error: cannot send ieof for istate %d", + error("channel %d: cannot send ieof for istate %d", c->self, c->istate); break; } @@ -234,15 +250,14 @@ switch (c->ostate) { case CHAN_OUTPUT_OPEN: case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); - buffer_consume(&c->output, buffer_len(&c->output)); + buffer_clear(&c->output); packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); packet_put_int(c->remote_id); packet_send(); break; default: - error("channel %d: internal error: cannot send oclose for ostate %d", - c->self, c->ostate); + error("channel %d: cannot send oclose for ostate %d", + c->self, c->ostate); break; } } @@ -251,7 +266,7 @@ * the same for SSH2 */ static void -chan_rcvd_oclose2(Channel *c) +chan_rcvd_close2(Channel *c) { debug("channel %d: rcvd close", c->self); if (c->flags & CHAN_CLOSE_RCVD) @@ -259,59 +274,37 @@ c->flags |= CHAN_CLOSE_RCVD; if (c->type == SSH_CHANNEL_LARVAL) { /* tear down larval channels immediately */ - c->ostate = CHAN_OUTPUT_CLOSED; - c->istate = CHAN_INPUT_CLOSED; + chan_set_ostate(c, CHAN_OUTPUT_CLOSED); + chan_set_istate(c, CHAN_INPUT_CLOSED); return; } switch (c->ostate) { case CHAN_OUTPUT_OPEN: - /* wait until a data from the channel is consumed if a CLOSE is received */ - debug("channel %d: output open -> drain", c->self); - c->ostate = CHAN_OUTPUT_WAIT_DRAIN; + /* + * wait until a data from the channel is consumed if a CLOSE + * is received + */ + chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); break; } switch (c->istate) { case CHAN_INPUT_OPEN: - debug("channel %d: input open -> closed", c->self); chan_shutdown_read(c); + chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_WAIT_DRAIN: - debug("channel %d: input drain -> closed", c->self); chan_send_eof2(c); - break; - } - c->istate = CHAN_INPUT_CLOSED; -} -static void -chan_ibuf_empty2(Channel *c) -{ - debug("channel %d: ibuf empty", c->self); - if (buffer_len(&c->input)) { - error("channel %d: internal error: chan_ibuf_empty for non empty buffer", - c->self); - return; - } - switch (c->istate) { - case CHAN_INPUT_WAIT_DRAIN: - debug("channel %d: input drain -> closed", c->self); - if (!(c->flags & CHAN_CLOSE_SENT)) - chan_send_eof2(c); - c->istate = CHAN_INPUT_CLOSED; - break; - default: - error("channel %d: internal error: chan_ibuf_empty for istate %d", - c->self, c->istate); + chan_set_istate(c, CHAN_INPUT_CLOSED); break; } } static void -chan_rcvd_ieof2(Channel *c) +chan_rcvd_eof2(Channel *c) { debug("channel %d: rcvd eof", c->self); - if (c->ostate == CHAN_OUTPUT_OPEN) { - debug("channel %d: output open -> drain", c->self); - c->ostate = CHAN_OUTPUT_WAIT_DRAIN; - } + c->flags |= CHAN_EOF_RCVD; + if (c->ostate == CHAN_OUTPUT_OPEN) + chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); } static void chan_write_failed2(Channel *c) @@ -319,38 +312,12 @@ debug("channel %d: write failed", c->self); switch (c->ostate) { case CHAN_OUTPUT_OPEN: - debug("channel %d: output open -> closed", c->self); - chan_shutdown_write(c); /* ?? */ - c->ostate = CHAN_OUTPUT_CLOSED; - break; case CHAN_OUTPUT_WAIT_DRAIN: - debug("channel %d: output drain -> closed", c->self); chan_shutdown_write(c); - c->ostate = CHAN_OUTPUT_CLOSED; + chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: - error("channel %d: internal error: chan_write_failed for ostate %d", - c->self, c->ostate); - break; - } -} -static void -chan_obuf_empty2(Channel *c) -{ - debug("channel %d: obuf empty", c->self); - if (buffer_len(&c->output)) { - error("internal error: chan_obuf_empty %d for non empty buffer", - c->self); - return; - } - switch (c->ostate) { - case CHAN_OUTPUT_WAIT_DRAIN: - debug("channel %d: output drain -> closed", c->self); - chan_shutdown_write(c); - c->ostate = CHAN_OUTPUT_CLOSED; - break; - default: - error("channel %d: internal error: chan_obuf_empty for ostate %d", + error("channel %d: chan_write_failed for ostate %d", c->self, c->ostate); break; } @@ -364,9 +331,10 @@ packet_start(SSH2_MSG_CHANNEL_EOF); packet_put_int(c->remote_id); packet_send(); + c->flags |= CHAN_EOF_SENT; break; default: - error("channel %d: internal error: cannot send eof for istate %d", + error("channel %d: cannot send eof for istate %d", c->self, c->istate); break; } @@ -377,10 +345,10 @@ debug("channel %d: send close", c->self); if (c->ostate != CHAN_OUTPUT_CLOSED || c->istate != CHAN_INPUT_CLOSED) { - error("channel %d: internal error: cannot send close for istate/ostate %d/%d", + error("channel %d: cannot send close for istate/ostate %d/%d", c->self, c->istate, c->ostate); } else if (c->flags & CHAN_CLOSE_SENT) { - error("channel %d: internal error: already sent close", c->self); + error("channel %d: already sent close", c->self); } else { packet_start(SSH2_MSG_CHANNEL_CLOSE); packet_put_int(c->remote_id); @@ -391,92 +359,101 @@ /* shared */ +void +chan_rcvd_ieof(Channel *c) +{ + if (compat20) + chan_rcvd_eof2(c); + else + chan_rcvd_ieof1(c); + if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && + buffer_len(&c->output) == 0 && + !CHANNEL_EFD_OUTPUT_ACTIVE(c)) + chan_obuf_empty(c); +} +void +chan_rcvd_oclose(Channel *c) +{ + if (compat20) + chan_rcvd_close2(c); + else + chan_rcvd_oclose1(c); +} +void +chan_write_failed(Channel *c) +{ + if (compat20) + chan_write_failed2(c); + else + chan_write_failed1(c); +} + +void +chan_mark_dead(Channel *c) +{ + c->type = SSH_CHANNEL_ZOMBIE; +} + int -chan_is_dead(Channel *c) +chan_is_dead(Channel *c, int send) { + if (c->type == SSH_CHANNEL_ZOMBIE) { + debug("channel %d: zombie", c->self); + return 1; + } if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) return 0; if (!compat20) { debug("channel %d: is dead", c->self); return 1; } - /* - * we have to delay the close message if the efd (for stderr) is - * still active - */ - if (((c->extended_usage != CHAN_EXTENDED_IGNORE) && - buffer_len(&c->extended) > 0) -#if 0 - || ((c->extended_usage == CHAN_EXTENDED_READ) && - c->efd != -1) -#endif - ) { - debug2("channel %d: active efd: %d len %d type %s", - c->self, c->efd, buffer_len(&c->extended), - c->extended_usage==CHAN_EXTENDED_READ ? - "read": "write"); - } else { - if (!(c->flags & CHAN_CLOSE_SENT)) { + if ((datafellows & SSH_BUG_EXTEOF) && + c->extended_usage == CHAN_EXTENDED_WRITE && + c->efd != -1 && + buffer_len(&c->extended) > 0) { + debug2("channel %d: active efd: %d len %d", + c->self, c->efd, buffer_len(&c->extended)); + return 0; + } + if (!(c->flags & CHAN_CLOSE_SENT)) { + if (send) { chan_send_close2(c); - } - if ((c->flags & CHAN_CLOSE_SENT) && - (c->flags & CHAN_CLOSE_RCVD)) { - debug("channel %d: is dead", c->self); - return 1; + } else { + /* channel would be dead if we sent a close */ + if (c->flags & CHAN_CLOSE_RCVD) { + debug("channel %d: almost dead", + c->self); + return 1; + } } } - return 0; -} - -void -chan_init_iostates(Channel *c) -{ - c->ostate = CHAN_OUTPUT_OPEN; - c->istate = CHAN_INPUT_OPEN; - c->flags = 0; -} - -/* init */ -void -chan_init(void) -{ - if (compat20) { - chan_rcvd_oclose = chan_rcvd_oclose2; - chan_read_failed = chan_read_failed_12; - chan_ibuf_empty = chan_ibuf_empty2; - - chan_rcvd_ieof = chan_rcvd_ieof2; - chan_write_failed = chan_write_failed2; - chan_obuf_empty = chan_obuf_empty2; - } else { - chan_rcvd_oclose = chan_rcvd_oclose1; - chan_read_failed = chan_read_failed_12; - chan_ibuf_empty = chan_ibuf_empty1; - - chan_rcvd_ieof = chan_rcvd_ieof1; - chan_write_failed = chan_write_failed1; - chan_obuf_empty = chan_obuf_empty1; + if ((c->flags & CHAN_CLOSE_SENT) && + (c->flags & CHAN_CLOSE_RCVD)) { + debug("channel %d: is dead", c->self); + return 1; } + return 0; } /* helper */ static void chan_shutdown_write(Channel *c) { - buffer_consume(&c->output, buffer_len(&c->output)); + buffer_clear(&c->output); if (compat20 && c->type == SSH_CHANNEL_LARVAL) return; /* shutdown failure is allowed if write failed already */ debug("channel %d: close_write", c->self); if (c->sock != -1) { if (shutdown(c->sock, SHUT_WR) < 0) - debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s", + debug("channel %d: chan_shutdown_write: " + "shutdown() failed for fd%d: %.100s", c->self, c->sock, strerror(errno)); } else { - if (close(c->wfd) < 0) - log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s", + if (channel_close_fd(&c->wfd) < 0) + log("channel %d: chan_shutdown_write: " + "close() failed for fd%d: %.100s", c->self, c->wfd, strerror(errno)); - c->wfd = -1; } } static void @@ -486,13 +463,21 @@ return; debug("channel %d: close_read", c->self); if (c->sock != -1) { - if (shutdown(c->sock, SHUT_RD) < 0) - error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s", - c->self, c->sock, c->istate, c->ostate, strerror(errno)); + /* + * shutdown(sock, SHUT_READ) may return ENOTCONN if the + * write side has been closed already. (bug on Linux) + * HP-UX may return ENOTCONN also. + */ + if (shutdown(c->sock, SHUT_RD) < 0 + && errno != ENOTCONN) + error("channel %d: chan_shutdown_read: " + "shutdown() failed for fd%d [i%d o%d]: %.100s", + c->self, c->sock, c->istate, c->ostate, + strerror(errno)); } else { - if (close(c->rfd) < 0) - log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s", + if (channel_close_fd(&c->rfd) < 0) + log("channel %d: chan_shutdown_read: " + "close() failed for fd%d: %.100s", c->self, c->rfd, strerror(errno)); - c->rfd = -1; } } Index: src/crypto/openssh/nchan.h =================================================================== RCS file: src/crypto/openssh/nchan.h diff -N src/crypto/openssh/nchan.h --- src/crypto/openssh/nchan.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 1999 Markus Friedl. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* RCSID("$OpenBSD: nchan.h,v 1.10 2001/02/28 08:54:55 markus Exp $"); */ - -#ifndef NCHAN_H -#define NCHAN_H - -/* - * SSH Protocol 1.5 aka New Channel Protocol - * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored. - * Written by Markus Friedl in October 1999 - * - * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the - * tear down of channels: - * - * 1.3: strict request-ack-protocol: - * CLOSE -> - * <- CLOSE_CONFIRM - * - * 1.5: uses variations of: - * IEOF -> - * <- OCLOSE - * <- IEOF - * OCLOSE -> - * i.e. both sides have to close the channel - * - * See the debugging output from 'ssh -v' and 'sshd -d' of - * ssh-1.2.27 as an example. - * - */ - -/* ssh-proto-1.5 overloads prot-1.3-message-types */ -#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE -#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION - -/* possible input states */ -#define CHAN_INPUT_OPEN 0x01 -#define CHAN_INPUT_WAIT_DRAIN 0x02 -#define CHAN_INPUT_WAIT_OCLOSE 0x04 -#define CHAN_INPUT_CLOSED 0x08 - -/* possible output states */ -#define CHAN_OUTPUT_OPEN 0x10 -#define CHAN_OUTPUT_WAIT_DRAIN 0x20 -#define CHAN_OUTPUT_WAIT_IEOF 0x40 -#define CHAN_OUTPUT_CLOSED 0x80 - -#define CHAN_CLOSE_SENT 0x01 -#define CHAN_CLOSE_RCVD 0x02 - - -/* Channel EVENTS */ -typedef void chan_event_fn(Channel * c); - -/* for the input state */ -extern chan_event_fn *chan_rcvd_oclose; -extern chan_event_fn *chan_read_failed; -extern chan_event_fn *chan_ibuf_empty; - -/* for the output state */ -extern chan_event_fn *chan_rcvd_ieof; -extern chan_event_fn *chan_write_failed; -extern chan_event_fn *chan_obuf_empty; - -int chan_is_dead(Channel * c); - -void chan_init_iostates(Channel * c); -void chan_init(void); -#endif Index: src/crypto/openssh/nchan2.ms =================================================================== RCS file: /home/ncvs/src/crypto/openssh/nchan2.ms,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 nchan2.ms --- src/crypto/openssh/nchan2.ms 9 Jun 2000 07:10:20 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/nchan2.ms 30 Jun 2002 11:37:59 -0000 @@ -1,3 +1,27 @@ +.\" $OpenBSD: nchan2.ms,v 1.2 2001/10/03 10:05:57 markus Exp $ +.\" +.\" Copyright (c) 2000 Markus Friedl. 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" .TL OpenSSH Channel Close Protocol 2.0 Implementation .SH Index: src/crypto/openssh/packet.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/packet.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 packet.c --- src/crypto/openssh/packet.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/packet.c 30 Jun 2002 11:37:59 -0000 @@ -13,7 +13,7 @@ * * * SSH2 packet format added by Markus Friedl. - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: packet.c,v 1.61 2001/04/05 10:42:51 markus Exp $"); +RCSID("$OpenBSD: packet.c,v 1.96 2002/06/23 21:10:02 deraadt Exp $"); #include "xmalloc.h" #include "buffer.h" @@ -59,6 +59,8 @@ #include "mac.h" #include "log.h" #include "canohost.h" +#include "misc.h" +#include "ssh.h" #ifdef PACKET_DEBUG #define DBG(x) x @@ -75,12 +77,6 @@ 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 u_int remote_protocol_flags = 0; @@ -91,10 +87,10 @@ static CipherContext send_context; /* Buffer for raw input data from the socket. */ -static Buffer input; +Buffer input; /* Buffer for raw output data going to the socket. */ -static Buffer output; +Buffer output; /* Buffer for the partial outgoing packet being constructed. */ static Buffer outgoing_packet; @@ -118,19 +114,17 @@ /* Set to true if the connection is interactive. */ static int interactive_mode = 0; -/* True if SSH2 packet format is used */ -int use_ssh2_packet_format = 0; - /* Session key information for Encryption and MAC */ Newkeys *newkeys[MODE_MAX]; +static u_int32_t read_seqnr = 0; +static u_int32_t send_seqnr = 0; -void -packet_set_ssh2_format(void) -{ - DBG(debug("use_ssh2_packet_format")); - use_ssh2_packet_format = 1; - newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; -} +/* Session key for protocol v1 */ +static u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; +static u_int ssh1_keylen; + +/* roundup current message to extra_pad bytes */ +static u_char extra_pad = 0; /* * Sets the descriptors used for communication. Disables encryption until @@ -144,9 +138,9 @@ fatal("packet_set_connection: cannot load cipher 'none'"); connection_in = fd_in; connection_out = fd_out; - cipher_type = SSH_CIPHER_NONE; - cipher_init(&send_context, none, (u_char *) "", 0, NULL, 0); - cipher_init(&receive_context, none, (u_char *) "", 0, NULL, 0); + cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT); + cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT); + newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; if (!initialized) { initialized = 1; buffer_init(&input); @@ -161,7 +155,7 @@ /* Returns 1 if remote host is connected via socket, 0 if not. */ int -packet_connection_is_on_socket() +packet_connection_is_on_socket(void) { struct sockaddr_storage from, to; socklen_t fromlen, tolen; @@ -184,10 +178,103 @@ return 1; } +/* + * Exports an IV from the CipherContext required to export the key + * state back from the unprivileged child to the privileged parent + * process. + */ + +void +packet_get_keyiv(int mode, u_char *iv, u_int len) +{ + CipherContext *cc; + + if (mode == MODE_OUT) + cc = &send_context; + else + cc = &receive_context; + + cipher_get_keyiv(cc, iv, len); +} + +int +packet_get_keycontext(int mode, u_char *dat) +{ + CipherContext *cc; + + if (mode == MODE_OUT) + cc = &send_context; + else + cc = &receive_context; + + return (cipher_get_keycontext(cc, dat)); +} + +void +packet_set_keycontext(int mode, u_char *dat) +{ + CipherContext *cc; + + if (mode == MODE_OUT) + cc = &send_context; + else + cc = &receive_context; + + cipher_set_keycontext(cc, dat); +} + +int +packet_get_keyiv_len(int mode) +{ + CipherContext *cc; + + if (mode == MODE_OUT) + cc = &send_context; + else + cc = &receive_context; + + return (cipher_get_keyiv_len(cc)); +} +void +packet_set_iv(int mode, u_char *dat) +{ + CipherContext *cc; + + if (mode == MODE_OUT) + cc = &send_context; + else + cc = &receive_context; + + cipher_set_keyiv(cc, dat); +} +int +packet_get_ssh1_cipher() +{ + return (cipher_get_number(receive_context.cipher)); +} + + +u_int32_t +packet_get_seqnr(int mode) +{ + return (mode == MODE_IN ? read_seqnr : send_seqnr); +} + +void +packet_set_seqnr(int mode, u_int32_t seqnr) +{ + if (mode == MODE_IN) + read_seqnr = seqnr; + else if (mode == MODE_OUT) + send_seqnr = seqnr; + else + fatal("packet_set_seqnr: bad mode %d", mode); +} + /* returns 1 if connection is via ipv4 */ int -packet_connection_is_ipv4() +packet_connection_is_ipv4(void) { struct sockaddr_storage to; socklen_t tolen = sizeof(to); @@ -195,15 +282,20 @@ memset(&to, 0, sizeof(to)); if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) return 0; - if (to.ss_family != AF_INET) - return 0; - return 1; + if (to.ss_family == AF_INET) + return 1; +#ifdef IPV4_IN_IPV6 + if (to.ss_family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) + return 1; +#endif + return 0; } /* Sets the connection into non-blocking mode. */ void -packet_set_nonblocking() +packet_set_nonblocking(void) { /* Set the socket into non-blocking mode. */ if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) @@ -218,7 +310,7 @@ /* Returns the socket used for reading. */ int -packet_get_connection_in() +packet_get_connection_in(void) { return connection_in; } @@ -226,7 +318,7 @@ /* Returns the descriptor used for writing. */ int -packet_get_connection_out() +packet_get_connection_out(void) { return connection_out; } @@ -234,7 +326,7 @@ /* Closes the connection and clears and frees internal data structures. */ void -packet_close() +packet_close(void) { if (!initialized) return; @@ -254,6 +346,8 @@ buffer_free(&compression_buffer); buffer_compress_uninit(); } + cipher_cleanup(&send_context); + cipher_cleanup(&receive_context); } /* Sets remote side protocol flags. */ @@ -262,13 +356,12 @@ packet_set_protocol_flags(u_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. */ u_int -packet_get_protocol_flags() +packet_get_protocol_flags(void) { return remote_protocol_flags; } @@ -278,8 +371,8 @@ * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */ -void -packet_init_compression() +static void +packet_init_compression(void) { if (compression_buffer_ready == 1) return; @@ -290,7 +383,7 @@ void packet_start_compression(int level) { - if (packet_compression && !use_ssh2_packet_format) + if (packet_compression && !compat20) fatal("Compression already enabled."); packet_compression = 1; packet_init_compression(); @@ -299,38 +392,6 @@ } /* - * 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, - u_int bytes) -{ - 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 *context, void *dest, void *src, u_int bytes) -{ - /* - * Cryptographic attack detector for ssh - Modifications for packet.c - * (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com) - */ - if (!compat20 && - context->cipher->number != SSH_CIPHER_NONE && - detect_attack(src, bytes, NULL) == DEATTACK_DETECTED) - packet_disconnect("crc32 compensation attack: network attack detected"); - - cipher_decrypt(context, 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. @@ -345,85 +406,65 @@ fatal("packet_set_encryption_key: unknown cipher number %d", number); if (keylen < 20) fatal("packet_set_encryption_key: keylen too small: %d", keylen); - cipher_init(&receive_context, cipher, key, keylen, NULL, 0); - cipher_init(&send_context, cipher, key, keylen, NULL, 0); + if (keylen > SSH_SESSION_KEY_LENGTH) + fatal("packet_set_encryption_key: keylen too big: %d", keylen); + memcpy(ssh1_key, key, keylen); + ssh1_keylen = keylen; + cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); + cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); } -/* Starts constructing a packet to send. */ - -void -packet_start1(int type) +u_int +packet_get_encryption_key(u_char *key) { - char buf[9]; - - buffer_clear(&outgoing_packet); - memset(buf, 0, 8); - buf[8] = type; - buffer_append(&outgoing_packet, buf, 9); + if (key == NULL) + return (ssh1_keylen); + memcpy(key, ssh1_key, ssh1_keylen); + return (ssh1_keylen); } +/* Start constructing a packet to send. */ void -packet_start2(int type) +packet_start(u_char type) { - char buf[4+1+1]; + u_char buf[9]; + int len; - buffer_clear(&outgoing_packet); - memset(buf, 0, sizeof buf); - /* buf[0..3] = payload_len; */ - /* buf[4] = pad_len; */ - buf[5] = type & 0xff; - buffer_append(&outgoing_packet, buf, sizeof buf); -} - -void -packet_start(int type) -{ DBG(debug("packet_start[%d]", type)); - if (use_ssh2_packet_format) - packet_start2(type); - else - packet_start1(type); + len = compat20 ? 6 : 9; + memset(buf, 0, len - 1); + buf[len - 1] = type; + buffer_clear(&outgoing_packet); + buffer_append(&outgoing_packet, buf, len); } -/* Appends a character to the packet data. */ - +/* Append payload. */ 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(u_int value) { buffer_put_int(&outgoing_packet, value); } - -/* Appends a string to packet data. */ - void -packet_put_string(const char *buf, u_int len) +packet_put_string(const void *buf, u_int len) { buffer_put_string(&outgoing_packet, buf, len); } void packet_put_cstring(const char *str) { - buffer_put_string(&outgoing_packet, str, strlen(str)); + buffer_put_cstring(&outgoing_packet, str); } - void -packet_put_raw(const char *buf, u_int len) +packet_put_raw(const void *buf, u_int len) { buffer_append(&outgoing_packet, buf, len); } - - -/* Appends an arbitrary precision integer to packet data. */ - void packet_put_bignum(BIGNUM * value) { @@ -440,10 +481,10 @@ * encrypts the packet before sending. */ -void +static void packet_send1(void) { - char buf[8], *cp; + u_char buf[8], *cp; int i, padding, len; u_int checksum; u_int32_t rand = 0; @@ -461,14 +502,14 @@ buffer_compress(&outgoing_packet, &compression_buffer); buffer_clear(&outgoing_packet); buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), - buffer_len(&compression_buffer)); + buffer_len(&compression_buffer)); } /* Compute packet length without padding (add checksum, remove padding). */ len = buffer_len(&outgoing_packet) + 4 - 8; /* Insert padding. Initialized to zero in packet_start1() */ padding = 8 - len % 8; - if (cipher_type != SSH_CIPHER_NONE) { + if (!send_context.plaintext) { cp = buffer_ptr(&outgoing_packet); for (i = 0; i < padding; i++) { if (i % 4 == 0) @@ -480,7 +521,7 @@ buffer_consume(&outgoing_packet, 8 - padding); /* Add check bytes. */ - checksum = ssh_crc32((u_char *) buffer_ptr(&outgoing_packet), + checksum = ssh_crc32(buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet)); PUT_32BIT(buf, checksum); buffer_append(&outgoing_packet, buf, 4); @@ -493,9 +534,9 @@ /* 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)); + cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); + cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), + buffer_len(&outgoing_packet)); #ifdef PACKET_DEBUG fprintf(stderr, "encrypted: "); @@ -518,14 +559,20 @@ Mac *mac; Comp *comp; CipherContext *cc; + int encrypt; debug("newkeys: mode %d", mode); - cc = (mode == MODE_OUT) ? &send_context : &receive_context; + if (mode == MODE_OUT) { + cc = &send_context; + encrypt = CIPHER_ENCRYPT; + } else { + cc = &receive_context; + encrypt = CIPHER_DECRYPT; + } if (newkeys[mode] != NULL) { debug("newkeys: rekeying"); - /* todo: free old keys, reset compression/cipher-ctxt; */ - memset(cc, 0, sizeof(*cc)); + cipher_cleanup(cc); enc = &newkeys[mode]->enc; mac = &newkeys[mode]->mac; comp = &newkeys[mode]->comp; @@ -547,10 +594,11 @@ if (mac->md != NULL) mac->enabled = 1; DBG(debug("cipher_init_context: %d", mode)); - cipher_init(cc, enc->cipher, enc->key, enc->cipher->key_len, - enc->iv, enc->cipher->block_size); - memset(enc->iv, 0, enc->cipher->block_size); - memset(enc->key, 0, enc->cipher->key_len); + cipher_init(cc, enc->cipher, enc->key, enc->key_len, + enc->iv, enc->block_size, encrypt); + /* Deleting the keys does not gain extra security */ + /* memset(enc->iv, 0, enc->block_size); + memset(enc->key, 0, enc->key_len); */ if (comp->type != 0 && comp->enabled == 0) { packet_init_compression(); if (mode == MODE_OUT) @@ -564,16 +612,14 @@ /* * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) */ -void +static void packet_send2(void) { - static u_int32_t seqnr = 0; - u_char *macbuf = NULL; - char *cp; + u_char type, *cp, *macbuf = NULL; + u_char padlen, pad; u_int packet_length = 0; - u_int i, padlen, len; + u_int i, len; u_int32_t rand = 0; - int type; Enc *enc = NULL; Mac *mac = NULL; Comp *comp = NULL; @@ -584,10 +630,10 @@ mac = &newkeys[MODE_OUT]->mac; comp = &newkeys[MODE_OUT]->comp; } - block_size = enc ? enc->cipher->block_size : 8; + block_size = enc ? enc->block_size : 8; cp = buffer_ptr(&outgoing_packet); - type = cp[5] & 0xff; + type = cp[5]; #ifdef PACKET_DEBUG fprintf(stderr, "plain: "); @@ -618,8 +664,17 @@ padlen = block_size - (len % block_size); if (padlen < 4) padlen += block_size; - buffer_append_space(&outgoing_packet, &cp, padlen); - if (enc && enc->cipher->number != SSH_CIPHER_NONE) { + if (extra_pad) { + /* will wrap if extra_pad+padlen > 255 */ + extra_pad = roundup(extra_pad, block_size); + pad = extra_pad - ((len + padlen) % extra_pad); + debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", + pad, len, padlen, extra_pad); + padlen += pad; + extra_pad = 0; + } + cp = buffer_append_space(&outgoing_packet, padlen); + if (enc && !send_context.plaintext) { /* random padding */ for (i = 0; i < padlen; i++) { if (i % 4 == 0) @@ -635,19 +690,19 @@ packet_length = buffer_len(&outgoing_packet) - 4; cp = buffer_ptr(&outgoing_packet); PUT_32BIT(cp, packet_length); - cp[4] = padlen & 0xff; + cp[4] = padlen; DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); /* compute MAC over seqnr and packet(length fields, payload, padding) */ if (mac && mac->enabled) { - macbuf = mac_compute(mac, seqnr, - (u_char *) buffer_ptr(&outgoing_packet), + macbuf = mac_compute(mac, send_seqnr, + buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet)); - DBG(debug("done calc MAC out #%d", seqnr)); + DBG(debug("done calc MAC out #%d", send_seqnr)); } /* encrypt packet and append to output buffer. */ - buffer_append_space(&output, &cp, buffer_len(&outgoing_packet)); - packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet), + cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); + cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet)); /* append unencrypted MAC */ if (mac && mac->enabled) @@ -657,7 +712,7 @@ buffer_dump(&output); #endif /* increment sequence number for outgoing packets */ - if (++seqnr == 0) + if (++send_seqnr == 0) log("outgoing seqnr wraps around"); buffer_clear(&outgoing_packet); @@ -666,9 +721,9 @@ } void -packet_send() +packet_send(void) { - if (use_ssh2_packet_format) + if (compat20) packet_send2(); else packet_send1(); @@ -682,7 +737,7 @@ */ int -packet_read(int *payload_len_ptr) +packet_read_seqnr(u_int32_t *seqnr_p) { int type, len; fd_set *setp; @@ -698,13 +753,13 @@ /* 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 (!use_ssh2_packet_format && ( + type = packet_read_poll_seqnr(seqnr_p); + if (!compat20 && ( 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); + packet_check_eom(); /* If we got a packet, return it. */ if (type != SSH_MSG_NONE) { xfree(setp); @@ -737,17 +792,23 @@ /* NOTREACHED */ } +int +packet_read(void) +{ + return packet_read_seqnr(NULL); +} + /* * 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) +packet_read_expect(int expected_type) { int type; - type = packet_read(payload_len_ptr); + type = packet_read(); if (type != expected_type) packet_disconnect("Protocol error: expected packet type %d, got %d", expected_type, type); @@ -760,28 +821,21 @@ * 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_poll1(int *payload_len_ptr) +static int +packet_read_poll1(void) { u_int len, padded_len; - u_char *ucp; - char buf[8], *cp; + u_char *cp, type; u_int checksum, stored_checksum; /* 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 = (u_char *) buffer_ptr(&input); - len = GET_32BIT(ucp); + cp = buffer_ptr(&input); + len = GET_32BIT(cp); if (len < 1 + 2 + 2 || len > 256 * 1024) packet_disconnect("Bad packet length %d.", len); padded_len = (len + 8) & ~7; @@ -795,10 +849,20 @@ /* Consume packet length. */ buffer_consume(&input, 4); - /* Copy data to incoming_packet. */ + /* + * Cryptographic attack detector for ssh + * (C)1998 CORE-SDI, Buenos Aires Argentina + * Ariel Futoransky(futo@core-sdi.com) + */ + if (!receive_context.plaintext && + detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED) + packet_disconnect("crc32 compensation attack: network attack detected"); + + /* Decrypt 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); + cp = buffer_append_space(&incoming_packet, padded_len); + cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); + buffer_consume(&input, padded_len); #ifdef PACKET_DEBUG @@ -807,25 +871,23 @@ #endif /* Compute packet checksum. */ - checksum = ssh_crc32((u_char *) buffer_ptr(&incoming_packet), + checksum = ssh_crc32(buffer_ptr(&incoming_packet), buffer_len(&incoming_packet) - 4); /* Skip padding. */ buffer_consume(&incoming_packet, 8 - len % 8); /* Test check bytes. */ - if (len != buffer_len(&incoming_packet)) - packet_disconnect("packet_read_poll: len %d != buffer_len %d.", + packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", len, buffer_len(&incoming_packet)); - ucp = (u_char *) buffer_ptr(&incoming_packet) + len - 4; - stored_checksum = GET_32BIT(ucp); + cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; + stored_checksum = GET_32BIT(cp); if (checksum != stored_checksum) packet_disconnect("Corrupted check bytes on input."); buffer_consume_end(&incoming_packet, 4); - /* If using packet compression, decompress the packet. */ if (packet_compression) { buffer_clear(&compression_buffer); buffer_uncompress(&incoming_packet, &compression_buffer); @@ -833,26 +895,16 @@ buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), buffer_len(&compression_buffer)); } - /* Get packet type. */ - buffer_get(&incoming_packet, &buf[0], 1); - - /* Return length of payload (without type field). */ - *payload_len_ptr = buffer_len(&incoming_packet); - - /* Return type. */ - return (u_char) buf[0]; + type = buffer_get_char(&incoming_packet); + return type; } -int -packet_read_poll2(int *payload_len_ptr) +static int +packet_read_poll2(u_int32_t *seqnr_p) { - static u_int32_t seqnr = 0; static u_int packet_length = 0; u_int padlen, need; - u_char buf[8], *macbuf; - u_char *ucp; - char *cp; - int type; + u_char *macbuf, *cp, type; int maclen, block_size; Enc *enc = NULL; Mac *mac = NULL; @@ -864,7 +916,7 @@ comp = &newkeys[MODE_IN]->comp; } maclen = mac && mac->enabled ? mac->mac_len : 0; - block_size = enc ? enc->cipher->block_size : 8; + block_size = enc ? enc->block_size : 8; if (packet_length == 0) { /* @@ -874,11 +926,11 @@ if (buffer_len(&input) < block_size) return SSH_MSG_NONE; buffer_clear(&incoming_packet); - buffer_append_space(&incoming_packet, &cp, block_size); - packet_decrypt(&receive_context, cp, buffer_ptr(&input), + cp = buffer_append_space(&incoming_packet, block_size); + cipher_crypt(&receive_context, cp, buffer_ptr(&input), block_size); - ucp = (u_char *) buffer_ptr(&incoming_packet); - packet_length = GET_32BIT(ucp); + cp = buffer_ptr(&incoming_packet); + packet_length = GET_32BIT(cp); if (packet_length < 1 + 4 || packet_length > 256 * 1024) { buffer_dump(&incoming_packet); packet_disconnect("Bad packet length %d.", packet_length); @@ -903,28 +955,30 @@ fprintf(stderr, "read_poll enc/full: "); buffer_dump(&input); #endif - buffer_append_space(&incoming_packet, &cp, need); - packet_decrypt(&receive_context, cp, buffer_ptr(&input), need); + cp = buffer_append_space(&incoming_packet, need); + cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); buffer_consume(&input, need); /* * compute MAC over seqnr and packet, * increment sequence number for incoming packet */ if (mac && mac->enabled) { - macbuf = mac_compute(mac, seqnr, - (u_char *) buffer_ptr(&incoming_packet), + macbuf = mac_compute(mac, read_seqnr, + buffer_ptr(&incoming_packet), buffer_len(&incoming_packet)); if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) packet_disconnect("Corrupted MAC on input."); - DBG(debug("MAC #%d ok", seqnr)); + DBG(debug("MAC #%d ok", read_seqnr)); buffer_consume(&input, mac->mac_len); } - if (++seqnr == 0) + if (seqnr_p != NULL) + *seqnr_p = read_seqnr; + if (++read_seqnr == 0) log("incoming seqnr wraps around"); /* get padlen */ - cp = buffer_ptr(&incoming_packet) + 4; - padlen = *cp & 0xff; + cp = buffer_ptr(&incoming_packet); + padlen = cp[4]; DBG(debug("input: padlen %d", padlen)); if (padlen < 4) packet_disconnect("Corrupted padlen %d on input.", padlen); @@ -946,39 +1000,31 @@ * get packet type, implies consume. * return length of payload (without type field) */ - buffer_get(&incoming_packet, (char *)&buf[0], 1); - *payload_len_ptr = buffer_len(&incoming_packet); - - /* reset for next packet */ - packet_length = 0; - - /* extract packet type */ - type = (u_char)buf[0]; - + type = buffer_get_char(&incoming_packet); if (type == SSH2_MSG_NEWKEYS) set_newkeys(MODE_IN); - #ifdef PACKET_DEBUG fprintf(stderr, "read/plain[%d]:\r\n", type); buffer_dump(&incoming_packet); #endif - return (u_char)type; + /* reset for next packet */ + packet_length = 0; + return type; } int -packet_read_poll(int *payload_len_ptr) +packet_read_poll_seqnr(u_int32_t *seqnr_p) { + u_int reason, seqnr; + u_char type; char *msg; + for (;;) { - int type = use_ssh2_packet_format ? - packet_read_poll2(payload_len_ptr): - packet_read_poll1(payload_len_ptr); - - if(compat20) { - int reason; - if (type != 0) + if (compat20) { + type = packet_read_poll2(seqnr_p); + if (type) DBG(debug("received packet type %d", type)); - switch(type) { + switch (type) { case SSH2_MSG_IGNORE: break; case SSH2_MSG_DEBUG: @@ -992,17 +1038,23 @@ case SSH2_MSG_DISCONNECT: reason = packet_get_int(); msg = packet_get_string(NULL); - log("Received disconnect from %s: %d: %.400s", get_remote_ipaddr(), - reason, msg); + log("Received disconnect from %s: %u: %.400s", + get_remote_ipaddr(), reason, msg); xfree(msg); fatal_cleanup(); break; + case SSH2_MSG_UNIMPLEMENTED: + seqnr = packet_get_int(); + debug("Received SSH2_MSG_UNIMPLEMENTED for %u", + seqnr); + break; default: return type; break; } } else { - switch(type) { + type = packet_read_poll1(); + switch (type) { case SSH_MSG_IGNORE: break; case SSH_MSG_DEBUG: @@ -1012,13 +1064,13 @@ break; case SSH_MSG_DISCONNECT: msg = packet_get_string(NULL); - log("Received disconnect from %s: %.400s", get_remote_ipaddr(), - msg); + log("Received disconnect from %s: %.400s", + get_remote_ipaddr(), msg); fatal_cleanup(); xfree(msg); break; default: - if (type != 0) + if (type) DBG(debug("received packet type %d", type)); return type; break; @@ -1027,6 +1079,12 @@ } } +int +packet_read_poll(void) +{ + return packet_read_poll_seqnr(NULL); +} + /* * Buffers the given amount of input characters. This is intended to be used * together with packet_read_poll. @@ -1041,7 +1099,7 @@ /* Returns a character from the packet. */ u_int -packet_get_char() +packet_get_char(void) { char ch; buffer_get(&incoming_packet, &ch, 1); @@ -1051,7 +1109,7 @@ /* Returns an integer from the packet data. */ u_int -packet_get_int() +packet_get_int(void) { return buffer_get_int(&incoming_packet); } @@ -1062,18 +1120,18 @@ */ void -packet_get_bignum(BIGNUM * value, int *length_ptr) +packet_get_bignum(BIGNUM * value) { - *length_ptr = buffer_get_bignum(&incoming_packet, value); + buffer_get_bignum(&incoming_packet, value); } void -packet_get_bignum2(BIGNUM * value, int *length_ptr) +packet_get_bignum2(BIGNUM * value) { - *length_ptr = buffer_get_bignum2(&incoming_packet, value); + buffer_get_bignum2(&incoming_packet, value); } -char * +void * packet_get_raw(int *length_ptr) { int bytes = buffer_len(&incoming_packet); @@ -1095,7 +1153,7 @@ * integer into which the length of the string is stored. */ -char * +void * packet_get_string(u_int *length_ptr) { return buffer_get_string(&incoming_packet, length_ptr); @@ -1169,13 +1227,13 @@ packet_put_cstring(""); } else { packet_start(SSH_MSG_DISCONNECT); - packet_put_string(buf, strlen(buf)); + packet_put_cstring(buf); } packet_send(); packet_write_wait(); /* Stop listening for connections. */ - channel_stop_listening(); + channel_close_all(); /* Close the connection. */ packet_close(); @@ -1188,7 +1246,7 @@ /* Checks if there is any buffered output, and tries to write some of the output. */ void -packet_write_poll() +packet_write_poll(void) { int len = buffer_len(&output); if (len > 0) { @@ -1209,7 +1267,7 @@ */ void -packet_write_wait() +packet_write_wait(void) { fd_set *setp; @@ -1231,7 +1289,7 @@ /* Returns true if there is buffered data to write to the connection. */ int -packet_have_data_to_write() +packet_have_data_to_write(void) { return buffer_len(&output) != 0; } @@ -1239,7 +1297,7 @@ /* Returns true if there is not too much data to write to the connection. */ int -packet_not_very_much_data_to_write() +packet_not_very_much_data_to_write(void) { if (interactive_mode) return buffer_len(&output) < 16384; @@ -1253,9 +1311,10 @@ packet_set_interactive(int interactive) { static int called = 0; +#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) int lowdelay = IPTOS_LOWDELAY; int throughput = IPTOS_THROUGHPUT; - int on = 1; +#endif if (called) return; @@ -1275,30 +1334,32 @@ * Set IP options for an interactive connection. Use * IPTOS_LOWDELAY and TCP_NODELAY. */ +#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) if (packet_connection_is_ipv4()) { if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, - (void *) &lowdelay, sizeof(lowdelay)) < 0) + &lowdelay, sizeof(lowdelay)) < 0) error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno)); } - if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on, - sizeof(on)) < 0) - error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); +#endif + set_nodelay(connection_in); } else if (packet_connection_is_ipv4()) { /* * Set IP options for a non-interactive connection. Use * IPTOS_THROUGHPUT. */ - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &throughput, +#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) + if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, sizeof(throughput)) < 0) error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); +#endif } } /* Returns true if the current connection is interactive. */ int -packet_is_interactive() +packet_is_interactive(void) { return interactive_mode; } @@ -1316,11 +1377,19 @@ log("packet_set_maxsize: bad size %d", s); return -1; } - log("packet_set_maxsize: setting to %d", s); + called = 1; + debug("packet_set_maxsize: setting to %d", s); max_packet_size = s; return s; } +/* roundup current message to pad bytes */ +void +packet_add_padding(u_char pad) +{ + extra_pad = pad; +} + /* * 9.2. Ignored Data Message * @@ -1332,41 +1401,6 @@ * required to send them. This message can be used as an additional * protection measure against advanced traffic analysis techniques. */ -/* size of current + ignore message should be n*sumlen bytes (w/o mac) */ -void -packet_inject_ignore(int sumlen) -{ - int blocksize, padlen, have, need, nb, mini, nbytes; - Enc *enc = NULL; - - if (use_ssh2_packet_format == 0) - return; - - have = buffer_len(&outgoing_packet); - debug2("packet_inject_ignore: current %d", have); - if (newkeys[MODE_OUT] != NULL) - enc = &newkeys[MODE_OUT]->enc; - blocksize = enc ? enc->cipher->block_size : 8; - padlen = blocksize - (have % blocksize); - if (padlen < 4) - padlen += blocksize; - have += padlen; - have /= blocksize; /* # of blocks for current message */ - - nb = roundup(sumlen, blocksize) / blocksize; /* blocks for both */ - mini = roundup(5+1+4+4, blocksize) / blocksize; /* minsize ignore msg */ - need = nb - (have % nb); /* blocks for ignore */ - if (need <= mini) - need += nb; - nbytes = (need - mini) * blocksize; /* size of ignore payload */ - debug2("packet_inject_ignore: block %d have %d nb %d mini %d need %d", - blocksize, have, nb, mini, need); - - /* enqueue current message and append a ignore message */ - packet_send(); - packet_send_ignore(nbytes); -} - void packet_send_ignore(int nbytes) { @@ -1375,7 +1409,7 @@ packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); packet_put_int(nbytes); - for(i = 0; i < nbytes; i++) { + for (i = 0; i < nbytes; i++) { if (i % 4 == 0) rand = arc4random(); packet_put_char(rand & 0xff); Index: src/crypto/openssh/packet.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/packet.h,v retrieving revision 1.2.2.3 diff -u -u -r1.2.2.3 packet.h --- src/crypto/openssh/packet.h 28 Sep 2001 01:33:34 -0000 1.2.2.3 +++ src/crypto/openssh/packet.h 30 Jun 2002 11:38:00 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,191 +13,80 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: packet.h,v 1.22 2001/04/14 16:33:20 stevesk Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/packet.h,v 1.2.2.3 2001/09/28 01:33:34 green Exp $"); */ - #ifndef PACKET_H #define PACKET_H #include -/* - * 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); - -/* 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 u_char *key, u_int keylen, - int cipher_type); - -/* - * Sets remote side protocol flags for the current connection. This can be - * called at any time. - */ -void packet_set_protocol_flags(u_int flags); - -/* Returns the remote protocol flags set earlier by the above function. */ -u_int packet_get_protocol_flags(void); +void packet_set_connection(int, int); +void packet_set_nonblocking(void); +int packet_get_connection_in(void); +int packet_get_connection_out(void); +void packet_close(void); +void packet_set_encryption_key(const u_char *, u_int, int); +u_int packet_get_encryption_key(u_char *); +void packet_set_protocol_flags(u_int); +u_int packet_get_protocol_flags(void); +void packet_start_compression(int); +void packet_set_interactive(int); +int packet_is_interactive(void); + +void packet_start(u_char); +void packet_put_char(int ch); +void packet_put_int(u_int value); +void packet_put_bignum(BIGNUM * value); +void packet_put_bignum2(BIGNUM * value); +void packet_put_string(const void *buf, u_int len); +void packet_put_cstring(const char *str); +void packet_put_raw(const void *buf, u_int len); +void packet_send(void); + +int packet_read(void); +void packet_read_expect(int type); +int packet_read_poll(void); +void packet_process_incoming(const char *buf, u_int len); +int packet_read_seqnr(u_int32_t *seqnr_p); +int packet_read_poll_seqnr(u_int32_t *seqnr_p); + +u_int packet_get_char(void); +u_int packet_get_int(void); +void packet_get_bignum(BIGNUM * value); +void packet_get_bignum2(BIGNUM * value); +void *packet_get_raw(int *length_ptr); +void *packet_get_string(u_int *length_ptr); +void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2))); +void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); + +void set_newkeys(int mode); +int packet_get_keyiv_len(int); +void packet_get_keyiv(int, u_char *, u_int); +int packet_get_keycontext(int, u_char *); +void packet_set_keycontext(int, u_char *); +u_int32_t packet_get_seqnr(int); +void packet_set_seqnr(int, u_int32_t); +int packet_get_ssh1_cipher(void); +void packet_set_iv(int, u_char *); + +void packet_write_poll(void); +void packet_write_wait(void); +int packet_have_data_to_write(void); +int packet_not_very_much_data_to_write(void); + +int packet_connection_is_on_socket(void); +int packet_connection_is_ipv4(void); +int packet_remaining(void); +void packet_send_ignore(int); +void packet_add_padding(u_char); -/* Enables compression in both directions starting from the next packet. */ -void packet_start_compression(int level); +void tty_make_modes(int, struct termios *); +void tty_parse_modes(int, int *); -/* - * Informs that the current session is interactive. Sets IP flags for - * optimal performance in interactive use. - */ -void packet_set_interactive(int interactive); - -/* 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(u_int value); - -/* Appends an arbitrary precision integer to packet data. */ -void packet_put_bignum(BIGNUM * value); -void packet_put_bignum2(BIGNUM * value); - -/* Appends a string to packet data. */ -void packet_put_string(const char *buf, u_int len); -void packet_put_cstring(const char *str); -void packet_put_raw(const char *buf, u_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, u_int len); - -/* Returns a character (0-255) from the packet data. */ -u_int packet_get_char(void); - -/* Returns an integer from the packet data. */ -u_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_bignum(BIGNUM * value, int *length_ptr); -void packet_get_bignum2(BIGNUM * value, int *length_ptr); -char *packet_get_raw(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(u_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,...) __attribute__((format(printf, 1, 2))); - -/* - * 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,...) __attribute__((format(printf, 1, 2))); - -/* 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); - -/* maximum packet size, requested by client with SSH_CMSG_MAX_PACKET_SIZE */ extern int max_packet_size; -int packet_set_maxsize(int s); -#define packet_get_maxsize() max_packet_size - -/* Stores tty modes from the fd or tiop into current packet. */ -void tty_make_modes(int fd, struct termios *tiop); - -/* Parses tty modes for the fd from the current packet. */ -void tty_parse_modes(int fd, int *n_bytes_ptr); +int packet_set_maxsize(int); +#define packet_get_maxsize() max_packet_size -#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) - -#define packet_done() \ +/* don't allow remaining bytes after the end of the message */ +#define packet_check_eom() \ do { \ int _len = packet_remaining(); \ if (_len > 0) { \ @@ -204,21 +95,5 @@ packet_disconnect("Packet integrity error."); \ } \ } while (0) - -/* remote host is connected via a socket/ipv4 */ -int packet_connection_is_on_socket(void); -int packet_connection_is_ipv4(void); - -/* enable SSH2 packet format */ -void packet_set_ssh2_format(void); - -/* returns remaining payload bytes */ -int packet_remaining(void); - -/* append an ignore message */ -void packet_send_ignore(int nbytes); - -/* add an ignore message and make sure size (current+ignore) = n*sumlen */ -void packet_inject_ignore(int sumlen); #endif /* PACKET_H */ Index: src/crypto/openssh/pathnames.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/pathnames.h,v retrieving revision 1.2.2.1 diff -u -u -r1.2.2.1 pathnames.h --- src/crypto/openssh/pathnames.h 28 Sep 2001 01:33:34 -0000 1.2.2.1 +++ src/crypto/openssh/pathnames.h 30 Jun 2002 11:38:00 -0000 @@ -1,5 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.5 2001/04/12 19:15:24 markus Exp $ */ -/* $FreeBSD: src/crypto/openssh/pathnames.h,v 1.2.2.1 2001/09/28 01:33:34 green Exp $ */ +/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */ /* * Author: Tatu Ylonen @@ -13,28 +12,40 @@ * called by a name other than "ssh" or "Secure Shell". */ -#define ETCDIR "/etc/ssh" +#define ETCDIR "/etc" + +#ifndef SSHDIR +#define SSHDIR ETCDIR "/ssh" +#endif + +#ifndef _PATH_SSH_PIDDIR #define _PATH_SSH_PIDDIR "/var/run" +#endif /* * System-wide file containing host keys of known hosts. This file should be * world-readable. */ -#define _PATH_SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts" -#define _PATH_SSH_SYSTEM_HOSTFILE2 ETCDIR "/ssh_known_hosts2" +#define _PATH_SSH_SYSTEM_HOSTFILE SSHDIR "/ssh_known_hosts" +/* backward compat for protocol 2 */ +#define _PATH_SSH_SYSTEM_HOSTFILE2 SSHDIR "/ssh_known_hosts2" /* * Of these, ssh_host_key must be readable only by root, whereas ssh_config * should be world-readable. */ -#define _PATH_SERVER_CONFIG_FILE ETCDIR "/sshd_config" -#define _PATH_HOST_CONFIG_FILE ETCDIR "/ssh_config" -#define _PATH_HOST_KEY_FILE ETCDIR "/ssh_host_key" -#define _PATH_HOST_DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key" -#define _PATH_HOST_RSA_KEY_FILE ETCDIR "/ssh_host_rsa_key" -#define _PATH_DH_PRIMES ETCDIR "/primes" +#define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" +#define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" +#define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key" +#define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" +#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" +#define _PATH_DH_MODULI SSHDIR "/moduli" +/* Backwards compatibility */ +#define _PATH_DH_PRIMES SSHDIR "/primes" +#ifndef _PATH_SSH_PROGRAM #define _PATH_SSH_PROGRAM "/usr/bin/ssh" +#endif /* * The process id of the daemon listening for connections is saved here to @@ -54,6 +65,7 @@ * contain anything particularly secret. */ #define _PATH_SSH_USER_HOSTFILE "~/.ssh/known_hosts" +/* backward compat for protocol 2 */ #define _PATH_SSH_USER_HOSTFILE2 "~/.ssh/known_hosts2" /* @@ -81,6 +93,8 @@ * running as root.) */ #define _PATH_SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys" + +/* backward compat for protocol v2 */ #define _PATH_SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2" /* @@ -90,23 +104,66 @@ * use. xauth will be run if neither of these exists. */ #define _PATH_SSH_USER_RC ".ssh/rc" -#define _PATH_SSH_SYSTEM_RC ETCDIR "/sshrc" +#define _PATH_SSH_SYSTEM_RC SSHDIR "/sshrc" /* * Ssh-only version of /etc/hosts.equiv. Additionally, the daemon may use * ~/.rhosts and /etc/hosts.equiv if rhosts authentication is enabled. */ -#define _PATH_SSH_HOSTS_EQUIV ETCDIR "/shosts.equiv" +#define _PATH_SSH_HOSTS_EQUIV SSHDIR "/shosts.equiv" #define _PATH_RHOSTS_EQUIV "/etc/hosts.equiv" /* * Default location of askpass */ +#ifndef _PATH_SSH_ASKPASS_DEFAULT #define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass" +#endif + +/* Location of ssh-keysign for hostbased authentication */ +#ifndef _PATH_SSH_KEY_SIGN +#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign" +#endif + +/* xauth for X11 forwarding */ +#ifndef _PATH_XAUTH +#define _PATH_XAUTH "/usr/X11R6/bin/xauth" +#endif + +/* UNIX domain socket for X11 server; displaynum will replace %u */ +#ifndef _PATH_UNIX_X +#define _PATH_UNIX_X "/tmp/.X11-unix/X%u" +#endif /* for scp */ +#ifndef _PATH_CP #define _PATH_CP "cp" +#endif /* for sftp */ +#ifndef _PATH_SFTP_SERVER #define _PATH_SFTP_SERVER "/usr/libexec/sftp-server" +#endif + +/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */ +#ifndef _PATH_PRIVSEP_CHROOT_DIR +#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty" +#endif + +#ifndef _PATH_LS #define _PATH_LS "ls" +#endif + +/* path to login program */ +#ifndef LOGIN_PROGRAM +# ifdef LOGIN_PROGRAM_FALLBACK +# define LOGIN_PROGRAM LOGIN_PROGRAM_FALLBACK +# else +# define LOGIN_PROGRAM "/usr/bin/login" +# endif +#endif /* LOGIN_PROGRAM */ + +/* Askpass program define */ +#ifndef ASKPASS_PROGRAM +#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass" +#endif /* ASKPASS_PROGRAM */ Index: src/crypto/openssh/radix.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/radix.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 radix.c --- src/crypto/openssh/radix.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/radix.c 30 Jun 2002 11:38:00 -0000 @@ -1,5 +1,6 @@ /* * Copyright (c) 1999 Dug Song. All rights reserved. + * Copyright (c) 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,188 +26,132 @@ #include "includes.h" #include "uuencode.h" -RCSID("$OpenBSD: radix.c,v 1.15 2001/01/16 23:58:09 deraadt Exp $"); +RCSID("$OpenBSD: radix.c,v 1.21 2002/06/19 00:27:55 deraadt Exp $"); #ifdef AFS #include -typedef u_char my_u_char; -typedef u_int my_u_int32_t; -typedef u_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; \ -} +#include +#include "bufaux.h" -#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; \ -} +int +creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen) +{ + Buffer b; + int ret; -#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; \ -} + buffer_init(&b); -#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; \ -} + buffer_put_char(&b, 1); /* version */ + buffer_append(&b, creds->service, strlen(creds->service)); + buffer_put_char(&b, '\0'); + buffer_append(&b, creds->instance, strlen(creds->instance)); + buffer_put_char(&b, '\0'); + buffer_append(&b, creds->realm, strlen(creds->realm)); + buffer_put_char(&b, '\0'); + buffer_append(&b, creds->pname, strlen(creds->pname)); + buffer_put_char(&b, '\0'); + buffer_append(&b, creds->pinst, strlen(creds->pinst)); + buffer_put_char(&b, '\0'); -int -creds_to_radix(CREDENTIALS *creds, u_char *buf, size_t buflen) -{ - 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); - { - u_int endTime; - endTime = (u_int) 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; + buffer_put_char(&b, '\0'); - return (uuencode((u_char *)temp, len, (char *)buf, buflen)); -} + buffer_put_int(&b, creds->issue_date); + buffer_put_int(&b, krb_life_to_time(creds->issue_date, + creds->lifetime)); + buffer_append(&b, creds->session, sizeof(creds->session)); + buffer_put_short(&b, creds->kvno); + + /* 32 bit size + data */ + buffer_put_string(&b, creds->ticket_st.dat, creds->ticket_st.length); + + ret = uuencode(buffer_ptr(&b), buffer_len(&b), (char *)buf, buflen); + + buffer_free(&b); + return ret; +} + +#define GETSTRING(b, t, tlen) \ + do { \ + int i, found = 0; \ + for (i = 0; i < tlen; i++) { \ + if (buffer_len(b) == 0) \ + goto done; \ + t[i] = buffer_get_char(b); \ + if (t[i] == '\0') { \ + found = 1; \ + break; \ + } \ + } \ + if (!found) \ + goto done; \ + } while(0) int radix_to_creds(const char *buf, CREDENTIALS *creds) { + Buffer b; + char c, version, *space, *p; + u_int endTime; + int len, blen, ret; - char *p; - int len, tl; - char version; - char temp[2048]; + ret = 0; + blen = strlen(buf); - len = uudecode(buf, (u_char *)temp, sizeof(temp)); - if (len < 0) + /* sanity check for size */ + if (blen > 8192) return 0; - p = temp; + buffer_init(&b); + space = buffer_append_space(&b, blen); /* check version and length! */ + len = uudecode(buf, space, blen); if (len < 1) - return 0; - version = *p; - p++; - len--; - - GETSTRING(creds->service, p, len); - GETSTRING(creds->instance, p, len); - GETSTRING(creds->realm, p, len); + goto done; - 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--; + version = buffer_get_char(&b); - /* Enough space for remaining fixed-length parts? */ - if (len < (4 + 4 + sizeof(creds->session) + 2 + 4)) - return 0; + GETSTRING(&b, creds->service, sizeof creds->service); + GETSTRING(&b, creds->instance, sizeof creds->instance); + GETSTRING(&b, creds->realm, sizeof creds->realm); + GETSTRING(&b, creds->pname, sizeof creds->pname); + GETSTRING(&b, creds->pinst, sizeof creds->pinst); - GETLONG(creds->issue_date, p); - len -= 4; - { - u_int 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; + if (buffer_len(&b) == 0) + goto done; - tl = creds->ticket_st.length; - if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat)) - return 0; + /* Ignore possibly different realm. */ + while (buffer_len(&b) > 0 && (c = buffer_get_char(&b)) != '\0') + ; + + if (buffer_len(&b) == 0) + goto done; - memcpy(creds->ticket_st.dat, p, tl); - p += tl; - len -= tl; + creds->issue_date = buffer_get_int(&b); - return 1; + endTime = buffer_get_int(&b); + creds->lifetime = krb_time_to_life(creds->issue_date, endTime); + + len = buffer_len(&b); + if (len < sizeof(creds->session)) + goto done; + memcpy(&creds->session, buffer_ptr(&b), sizeof(creds->session)); + buffer_consume(&b, sizeof(creds->session)); + + creds->kvno = buffer_get_short(&b); + + p = buffer_get_string(&b, &len); + if (len < 0 || len > sizeof(creds->ticket_st.dat)) + goto done; + memcpy(&creds->ticket_st.dat, p, len); + creds->ticket_st.length = len; + + ret = 1; +done: + buffer_free(&b); + return ret; } #endif /* AFS */ Index: src/crypto/openssh/radix.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/radix.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 radix.h --- src/crypto/openssh/radix.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/radix.h 30 Jun 2002 11:38:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: radix.h,v 1.2 2001/01/29 01:58:17 niklas Exp $ */ +/* $OpenBSD: radix.h,v 1.4 2001/06/26 17:27:24 markus Exp $ */ /* * Copyright (c) 1999 Dug Song. All rights reserved. @@ -24,5 +24,5 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -int creds_to_radix(CREDENTIALS * creds, u_char *buf, size_t buflen); -int radix_to_creds(const char *buf, CREDENTIALS * creds); +int creds_to_radix(CREDENTIALS *, u_char *, size_t); +int radix_to_creds(const char *, CREDENTIALS *); Index: src/crypto/openssh/readconf.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/readconf.c,v retrieving revision 1.4.2.6 diff -u -u -r1.4.2.6 readconf.c --- src/crypto/openssh/readconf.c 28 Sep 2001 01:33:34 -0000 1.4.2.6 +++ src/crypto/openssh/readconf.c 30 Jun 2002 11:38:00 -0000 @@ -12,8 +12,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.76 2001/04/17 10:53:25 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/readconf.c,v 1.4.2.6 2001/09/28 01:33:34 green Exp $"); +RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/readconf.c,v 1.17 2002/06/29 10:51:56 des Exp $"); #include "ssh.h" #include "xmalloc.h" @@ -42,7 +42,7 @@ # that they are given in. Host *.ngs.fi ngs.fi - FallBackToRsh no + User foo Host fake.com HostName another.host.name.real.org @@ -66,7 +66,7 @@ ProxyCommand ssh-proxy %h %p Host *.fr - UseRsh yes + PublicKeyAuthentication no Host *.su Cipher none @@ -80,8 +80,6 @@ PasswordAuthentication yes RSAAuthentication yes RhostsRSAAuthentication yes - FallBackToRsh no - UseRsh no StrictHostKeyChecking yes KeepAlives no IdentityFile ~/.ssh/identity @@ -95,16 +93,16 @@ typedef enum { oBadOption, oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication, - oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh, + oPasswordAuthentication, oRSAAuthentication, oChallengeResponseAuthentication, oXAuthLocation, #if defined(KRB4) || defined(KRB5) oKerberosAuthentication, -#endif /* KRB4 */ -#ifdef KRB5 - oKrb5TgtPassing, -#endif /* KRB5 */ +#endif +#if defined(AFS) || defined(KRB5) + oKerberosTgtPassing, +#endif #ifdef AFS - oKrb4TgtPassing, oAFSTokenPassing, + oAFSTokenPassing, #endif oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, @@ -115,7 +113,10 @@ oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, - oHostKeyAlgorithms + oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, + oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oVersionAddendum, + oDeprecated } OpCodes; /* Textual representations of the tokens. */ @@ -143,16 +144,15 @@ { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ #if defined(KRB4) || defined(KRB5) { "kerberosauthentication", oKerberosAuthentication }, -#endif /* KRB4 || KRB5 */ -#ifdef KRB5 - { "kerberos5tgtpassing", oKrb5TgtPassing }, -#endif /* KRB5 */ +#endif +#if defined(AFS) || defined(KRB5) + { "kerberostgtpassing", oKerberosTgtPassing }, +#endif #ifdef AFS - { "kerberos4tgtpassing", oKrb4TgtPassing }, { "afstokenpassing", oAFSTokenPassing }, #endif - { "fallbacktorsh", oFallBackToRsh }, - { "usersh", oUseRsh }, + { "fallbacktorsh", oDeprecated }, + { "usersh", oDeprecated }, { "identityfile", oIdentityFile }, { "identityfile2", oIdentityFile }, /* alias */ { "hostname", oHostName }, @@ -169,9 +169,9 @@ { "host", oHost }, { "escapechar", oEscapeChar }, { "globalknownhostsfile", oGlobalKnownHostsFile }, - { "userknownhostsfile", oUserKnownHostsFile }, + { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, - { "userknownhostsfile2", oUserKnownHostsFile2 }, + { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ { "connectionattempts", oConnectionAttempts }, { "batchmode", oBatchMode }, { "checkhostip", oCheckHostIP }, @@ -184,7 +184,12 @@ { "dynamicforward", oDynamicForward }, { "preferredauthentications", oPreferredAuthentications }, { "hostkeyalgorithms", oHostKeyAlgorithms }, - { NULL, 0 } + { "bindaddress", oBindAddress }, + { "smartcarddevice", oSmartcardDevice }, + { "clearallforwardings", oClearAllForwardings }, + { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, + { "versionaddendum", oVersionAddendum }, + { NULL, oBadOption } }; /* @@ -197,9 +202,11 @@ u_short host_port) { Forward *fwd; +#ifndef HAVE_CYGWIN extern uid_t original_real_uid; if (port < IPPORT_RESERVED && original_real_uid != 0) fatal("Privileged ports can only be forwarded by root."); +#endif 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++]; @@ -220,13 +227,26 @@ Forward *fwd; if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("Too many remote forwards (max %d).", - SSH_MAX_FORWARDS_PER_DIRECTION); + 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; } +static void +clear_forwardings(Options *options) +{ + int i; + + for (i = 0; i < options->num_local_forwards; i++) + xfree(options->local_forwards[i].host); + options->num_local_forwards = 0; + for (i = 0; i < options->num_remote_forwards; i++) + xfree(options->remote_forwards[i].host); + options->num_remote_forwards = 0; +} + /* * Returns the number of the token pointed to by cp or oBadOption. */ @@ -258,6 +278,7 @@ char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg; int opcode, *intptr, value; u_short fwd_port, fwd_host_port; + char sfwd_host_port[6]; s = line; /* Get the keyword. (Each line is supposed to begin with a keyword). */ @@ -336,40 +357,24 @@ intptr = &options->hostbased_authentication; goto parse_flag; + case oChallengeResponseAuthentication: + intptr = &options->challenge_response_authentication; + goto parse_flag; #if defined(KRB4) || defined(KRB5) case oKerberosAuthentication: intptr = &options->kerberos_authentication; goto parse_flag; -#endif /* KRB4 || KRB5 */ - - case oChallengeResponseAuthentication: - intptr = &options->challenge_reponse_authentication; - goto parse_flag; - -#ifdef KRB5 - case oKrb5TgtPassing: - intptr = &options->krb5_tgt_passing; +#endif +#if defined(AFS) || defined(KRB5) + case oKerberosTgtPassing: + intptr = &options->kerberos_tgt_passing; goto parse_flag; -#endif /* KRB5 */ - +#endif #ifdef AFS - case oKrb4TgtPassing: - intptr = &options->krb4_tgt_passing; - goto parse_flag; - 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; @@ -383,7 +388,7 @@ arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing yes/no/ask argument.", - filename, linenum); + filename, linenum); value = 0; /* To avoid compiler warning... */ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) value = 1; @@ -405,6 +410,10 @@ intptr = &options->keepalives; goto parse_flag; + case oNoHostAuthenticationForLocalhost: + intptr = &options->no_host_authentication_for_localhost; + goto parse_flag; + case oNumberOfPasswordPrompts: intptr = &options->number_of_password_prompts; goto parse_int; @@ -421,7 +430,7 @@ intptr = &options->num_identity_files; if (*intptr >= SSH_MAX_IDENTITY_FILES) fatal("%.200s line %d: Too many identity files specified (max %d).", - filename, linenum, SSH_MAX_IDENTITY_FILES); + filename, linenum, SSH_MAX_IDENTITY_FILES); charptr = &options->identity_files[*intptr]; *charptr = xstrdup(arg); *intptr = *intptr + 1; @@ -470,6 +479,14 @@ charptr = &options->preferred_authentications; goto parse_string; + case oBindAddress: + charptr = &options->bind_address; + goto parse_string; + + case oSmartcardDevice: + charptr = &options->smartcard_device; + goto parse_string; + case oProxyCommand: charptr = &options->proxy_command; string = xstrdup(""); @@ -513,7 +530,7 @@ value = cipher_number(arg); if (value == -1) fatal("%.200s line %d: Bad cipher '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && *intptr == -1) *intptr = value; break; @@ -524,7 +541,7 @@ fatal("%.200s line %d: Missing argument.", filename, linenum); if (!ciphers_valid(arg)) fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && options->ciphers == NULL) options->ciphers = xstrdup(arg); break; @@ -535,7 +552,7 @@ fatal("%.200s line %d: Missing argument.", filename, linenum); if (!mac_valid(arg)) fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && options->macs == NULL) options->macs = xstrdup(arg); break; @@ -546,7 +563,7 @@ fatal("%.200s line %d: Missing argument.", filename, linenum); if (!key_names_valid2(arg)) fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && options->hostkeyalgorithms == NULL) options->hostkeyalgorithms = xstrdup(arg); break; @@ -559,7 +576,7 @@ value = proto_spec(arg); if (value == SSH_PROTO_UNKNOWN) fatal("%.200s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && *intptr == SSH_PROTO_UNKNOWN) *intptr = value; break; @@ -568,49 +585,41 @@ intptr = (int *) &options->log_level; arg = strdelim(&s); value = log_level_number(arg); - if (value == (LogLevel) - 1) + if (value == SYSLOG_LEVEL_NOT_SET) fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : ""); - if (*activep && (LogLevel) * intptr == -1) + filename, linenum, arg ? arg : ""); + if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) *intptr = (LogLevel) value; break; - case oRemoteForward: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - fwd_port = a2port(arg); - if (fwd_port == 0) - fatal("%.200s line %d: Badly formatted port number.", - filename, linenum); - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing second argument.", - filename, linenum); - if (sscanf(arg, "%255[^:]:%hu", 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: + case oRemoteForward: arg = strdelim(&s); if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - fwd_port = a2port(arg); - if (fwd_port == 0) - fatal("%.200s line %d: Badly formatted port number.", - filename, linenum); + fatal("%.200s line %d: Missing port argument.", + filename, linenum); + if ((fwd_port = a2port(arg)) == 0) + fatal("%.200s line %d: Bad listen port.", + filename, linenum); arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing second argument.", - filename, linenum); - if (sscanf(arg, "%255[^:]:%hu", 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); + filename, linenum); + if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && + sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) + fatal("%.200s line %d: Bad forwarding specification.", + filename, linenum); + if ((fwd_host_port = a2port(sfwd_host_port)) == 0) + fatal("%.200s line %d: Bad forwarding port.", + filename, linenum); + if (*activep) { + if (opcode == oLocalForward) + add_local_forward(options, fwd_port, buf, + fwd_host_port); + else if (opcode == oRemoteForward) + add_remote_forward(options, fwd_port, buf, + fwd_host_port); + } break; case oDynamicForward: @@ -622,9 +631,14 @@ if (fwd_port == 0) fatal("%.200s line %d: Badly formatted port number.", filename, linenum); - add_local_forward(options, fwd_port, "socks4", 0); + if (*activep) + add_local_forward(options, fwd_port, "socks4", 0); break; + case oClearAllForwardings: + intptr = &options->clear_forwardings; + goto parse_flag; + case oHost: *activep = 0; while ((arg = strdelim(&s)) != NULL && *arg != '\0') @@ -647,10 +661,10 @@ else if (strlen(arg) == 1) value = (u_char) arg[0]; else if (strcmp(arg, "none") == 0) - value = -2; + value = SSH_ESCAPECHAR_NONE; else { fatal("%.200s line %d: Bad escape character.", - filename, linenum); + filename, linenum); /* NOTREACHED */ value = 0; /* Avoid compiler warning. */ } @@ -658,6 +672,18 @@ *intptr = value; break; + case oVersionAddendum: + ssh_version_set_addendum(strtok(s, "\n")); + do { + arg = strdelim(&s); + } while (arg != NULL && *arg != '\0'); + break; + + case oDeprecated: + debug("%s line %d: Deprecated option \"%s\"", + filename, linenum, keyword); + return 0; + default: fatal("process_config_line: Unimplemented opcode %d", opcode); } @@ -665,7 +691,7 @@ /* Check that there is no garbage at end of line. */ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { fatal("%.200s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); + filename, linenum, arg); } return 0; } @@ -674,10 +700,10 @@ /* * 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. + * there is an error. If the file does not exist, this returns 0. */ -void +int read_config_file(const char *filename, const char *host, Options *options) { FILE *f; @@ -688,7 +714,7 @@ /* Open the file. */ f = fopen(filename, "r"); if (!f) - return; + return 0; debug("Reading configuration data %.200s", filename); @@ -707,7 +733,8 @@ fclose(f); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", - filename, bad_options); + filename, bad_options); + return 1; } /* @@ -729,15 +756,14 @@ options->rhosts_authentication = -1; options->rsa_authentication = -1; options->pubkey_authentication = -1; - options->challenge_reponse_authentication = -1; + options->challenge_response_authentication = -1; #if defined(KRB4) || defined(KRB5) options->kerberos_authentication = -1; #endif -#ifdef KRB5 - options->krb5_tgt_passing = -1; -#endif /* KRB5 */ +#if defined(AFS) || defined(KRB5) + options->kerberos_tgt_passing = -1; +#endif #ifdef AFS - options->krb4_tgt_passing = -1; options->afs_token_passing = -1; #endif options->password_authentication = -1; @@ -745,8 +771,6 @@ options->kbd_interactive_devices = NULL; options->rhosts_rsa_authentication = -1; options->hostbased_authentication = -1; - options->fallback_to_rsh = -1; - options->use_rsh = -1; options->batch_mode = -1; options->check_host_ip = -1; options->strict_host_key_checking = -1; @@ -773,8 +797,12 @@ options->user_hostfile2 = NULL; options->num_local_forwards = 0; options->num_remote_forwards = 0; - options->log_level = (LogLevel) - 1; + options->clear_forwardings = -1; + options->log_level = SYSLOG_LEVEL_NOT_SET; options->preferred_authentications = NULL; + options->bind_address = NULL; + options->smartcard_device = NULL; + options->no_host_authentication_for_localhost = - 1; } /* @@ -791,48 +819,40 @@ options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; -#ifdef XAUTH_PATH if (options->xauth_location == NULL) - options->xauth_location = XAUTH_PATH; -#endif /* XAUTH_PATH */ + options->xauth_location = _PATH_XAUTH; if (options->gateway_ports == -1) options->gateway_ports = 0; if (options->use_privileged_port == -1) options->use_privileged_port = 0; if (options->rhosts_authentication == -1) - options->rhosts_authentication = 1; + options->rhosts_authentication = 0; if (options->rsa_authentication == -1) options->rsa_authentication = 1; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; - if (options->challenge_reponse_authentication == -1) - options->challenge_reponse_authentication = 0; + if (options->challenge_response_authentication == -1) + options->challenge_response_authentication = 1; #if defined(KRB4) || defined(KRB5) if (options->kerberos_authentication == -1) options->kerberos_authentication = 1; -#endif /* KRB4 || KRB5 */ -#ifdef KRB5 - if (options->krb5_tgt_passing == -1) - options->krb5_tgt_passing = 1; -#endif /* KRB5 */ +#endif +#if defined(AFS) || defined(KRB5) + if (options->kerberos_tgt_passing == -1) + options->kerberos_tgt_passing = 1; +#endif #ifdef AFS - if (options->krb4_tgt_passing == -1) - options->krb4_tgt_passing = 1; if (options->afs_token_passing == -1) options->afs_token_passing = 1; -#endif /* AFS */ +#endif if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 1; if (options->rhosts_rsa_authentication == -1) - options->rhosts_rsa_authentication = 1; + options->rhosts_rsa_authentication = 0; if (options->hostbased_authentication == -1) options->hostbased_authentication = 0; - if (options->fallback_to_rsh == -1) - options->fallback_to_rsh = 0; - if (options->use_rsh == -1) - options->use_rsh = 0; if (options->batch_mode == -1) options->batch_mode = 0; if (options->check_host_ip == -1) @@ -848,7 +868,7 @@ if (options->port == -1) options->port = 0; /* Filled in ssh_connect. */ if (options->connection_attempts == -1) - options->connection_attempts = 4; + options->connection_attempts = 1; if (options->number_of_password_prompts == -1) options->number_of_password_prompts = 3; /* Selected in ssh_login(). */ @@ -891,8 +911,12 @@ options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; if (options->user_hostfile2 == NULL) options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; - if (options->log_level == (LogLevel) - 1) + if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; + if (options->clear_forwardings == 1) + clear_forwardings(options); + if (options->no_host_authentication_for_localhost == - 1) + options->no_host_authentication_for_localhost = 0; /* 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 */ Index: src/crypto/openssh/readconf.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/readconf.h,v retrieving revision 1.2.2.5 diff -u -u -r1.2.2.5 readconf.h --- src/crypto/openssh/readconf.h 28 Sep 2001 01:33:34 -0000 1.2.2.5 +++ src/crypto/openssh/readconf.h 30 Jun 2002 11:38:00 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: readconf.h,v 1.43 2002/06/08 05:17:01 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,9 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: readconf.h,v 1.30 2001/04/17 10:53:25 markus Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/readconf.h,v 1.2.2.5 2001/09/28 01:33:34 green Exp $"); */ - #ifndef READCONF_H #define READCONF_H @@ -40,27 +39,21 @@ int rsa_authentication; /* Try RSA authentication. */ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ - int challenge_reponse_authentication; + int challenge_response_authentication; /* Try S/Key or TIS, authentication. */ #if defined(KRB4) || defined(KRB5) - int kerberos_authentication; /* Try Kerberos - * authentication. */ + int kerberos_authentication; /* Try Kerberos authentication. */ +#endif +#if defined(AFS) || defined(KRB5) + int kerberos_tgt_passing; /* Try Kerberos TGT passing. */ #endif - -#ifdef KRB5 - int krb5_tgt_passing; -#endif /* KRB5 */ - #ifdef AFS - int krb4_tgt_passing; /* Try Kerberos v4 tgt passing. */ int afs_token_passing; /* Try AFS token passing. */ #endif int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ - 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 check_host_ip; /* Also keep track of keys for IP address */ int strict_host_key_checking; /* Strict host key checking. */ @@ -86,11 +79,13 @@ char *user; /* User to log in as. */ int escape_char; /* Escape character; -2 = none */ - char *system_hostfile;/* Path for /etc/ssh_known_hosts. */ + char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */ char *system_hostfile2; char *user_hostfile2; char *preferred_authentications; + char *bind_address; /* local socket address for connection to sshd */ + char *smartcard_device; /* Smartcard reader device */ int num_identity_files; /* Number of files for RSA/DSA identities. */ char *identity_files[SSH_MAX_IDENTITY_FILES]; @@ -103,56 +98,19 @@ /* Remote TCP/IP forward requests. */ int num_remote_forwards; Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; + int clear_forwardings; + int no_host_authentication_for_localhost; } 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); +void initialize_options(Options *); +void fill_default_options(Options *); +int read_config_file(const char *, const char *, Options *); -/* - * Processes a single option line as used in the configuration files. This - * only sets those values that have not already been set. Returns 0 for legal - * options - */ int -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); +process_config_line(Options *, const char *, char *, const char *, int, int *); -/* - * Adds a local TCP/IP port forward to options. Never returns if there is an - * error. - */ -void -add_local_forward(Options * options, u_short port, const char *host, - u_short host_port); - -/* - * Adds a remote TCP/IP port forward to options. Never returns if there is - * an error. - */ -void -add_remote_forward(Options * options, u_short port, const char *host, - u_short host_port); +void add_local_forward(Options *, u_short, const char *, u_short); +void add_remote_forward(Options *, u_short, const char *, u_short); #endif /* READCONF_H */ Index: src/crypto/openssh/readpass.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/readpass.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 readpass.c --- src/crypto/openssh/readpass.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/readpass.c 30 Jun 2002 11:38:00 -0000 @@ -1,6 +1,5 @@ /* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,55 +9,49 @@ * 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. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: readpass.c,v 1.15 2001/04/18 21:57:41 markus Exp $"); +RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $"); #include "xmalloc.h" -#include "cli.h" #include "readpass.h" #include "pathnames.h" #include "log.h" -#include "atomicio.h" #include "ssh.h" -char * -ssh_askpass(char *askpass, char *msg) +static char * +ssh_askpass(char *askpass, const char *msg) { pid_t pid; size_t len; - char *nl, *pass; - int p[2], status; + char *pass; + int p[2], status, ret; char buf[1024]; if (fflush(stdout) != 0) error("ssh_askpass: fflush: %s", strerror(errno)); if (askpass == NULL) fatal("internal error: askpass undefined"); - if (pipe(p) < 0) - fatal("ssh_askpass: pipe: %s", strerror(errno)); - if ((pid = fork()) < 0) - fatal("ssh_askpass: fork: %s", strerror(errno)); + if (pipe(p) < 0) { + error("ssh_askpass: pipe: %s", strerror(errno)); + return xstrdup(""); + } + if ((pid = fork()) < 0) { + error("ssh_askpass: fork: %s", strerror(errno)); + return xstrdup(""); + } if (pid == 0) { seteuid(getuid()); setuid(getuid()); @@ -69,43 +62,48 @@ fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno)); } close(p[1]); - len = read(p[0], buf, sizeof buf); + + len = ret = 0; + do { + ret = read(p[0], buf + len, sizeof(buf) - 1 - len); + if (ret == -1 && errno == EINTR) + continue; + if (ret <= 0) + break; + len += ret; + } while (sizeof(buf) - 1 - len > 0); + buf[len] = '\0'; + close(p[0]); while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) break; - if (len <= 1) - return xstrdup(""); - nl = strchr(buf, '\n'); - if (nl) - *nl = '\0'; + + buf[strcspn(buf, "\r\n")] = '\0'; pass = xstrdup(buf); memset(buf, 0, sizeof(buf)); return pass; } - -/* - * Reads a passphrase from /dev/tty with echo turned off. Returns the - * passphrase (allocated with xmalloc), being very careful to ensure that - * no other userland buffer is storing the password. - */ /* - * Note: the funcationallity of this routing has been moved to - * cli_read_passphrase(). This routing remains to maintain - * compatibility with existing code. + * Reads a passphrase from /dev/tty with echo turned off/on. Returns the + * passphrase (allocated with xmalloc). Exits if EOF is encountered. If + * RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no + * tty is available */ char * -read_passphrase(char *prompt, int from_stdin) +read_passphrase(const char *prompt, int flags) { - char *askpass = NULL; - int use_askpass = 0, ttyfd; + char *askpass = NULL, *ret, buf[1024]; + int rppflags, use_askpass = 0, ttyfd; - if (from_stdin) { + rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF; + if (flags & RP_ALLOW_STDIN) { if (!isatty(STDIN_FILENO)) use_askpass = 1; } else { - ttyfd = open("/dev/tty", O_RDWR); + rppflags |= RPP_REQUIRE_TTY; + ttyfd = open(_PATH_TTY, O_RDWR); if (ttyfd >= 0) close(ttyfd); else @@ -120,5 +118,13 @@ return ssh_askpass(askpass, prompt); } - return cli_read_passphrase(prompt, from_stdin, 0); + if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) { + if (flags & RP_ALLOW_EOF) + return NULL; + return xstrdup(""); + } + + ret = xstrdup(buf); + memset(buf, 'x', sizeof buf); + return ret; } Index: src/crypto/openssh/readpass.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/readpass.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 readpass.h --- src/crypto/openssh/readpass.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/readpass.h 30 Jun 2002 11:38:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: readpass.h,v 1.2 2001/01/29 01:58:17 niklas Exp $ */ +/* $OpenBSD: readpass.h,v 1.7 2002/03/26 15:58:46 markus Exp $ */ /* * Author: Tatu Ylonen @@ -12,9 +12,8 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* - * 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(char *prompt, int from_stdin); +#define RP_ECHO 0x0001 +#define RP_ALLOW_STDIN 0x0002 +#define RP_ALLOW_EOF 0x0004 + +char *read_passphrase(const char *, int); Index: src/crypto/openssh/rijndael.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/rijndael.c,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 rijndael.c --- src/crypto/openssh/rijndael.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/rijndael.c 30 Jun 2002 11:38:00 -0000 @@ -1,412 +1,1244 @@ -/* $OpenBSD: rijndael.c,v 1.7 2001/02/04 15:32:24 stevesk Exp $ */ +/* $OpenBSD: rijndael.c,v 1.13 2001/12/19 07:18:56 deraadt Exp $ */ -/* This is an independent implementation of the encryption algorithm: */ -/* */ -/* RIJNDAEL by Joan Daemen and Vincent Rijmen */ -/* */ -/* which is a candidate algorithm in the Advanced Encryption Standard */ -/* programme of the US National Institute of Standards and Technology. */ -/* */ -/* Copyright in this implementation is held by Dr B R Gladman but I */ -/* hereby give permission for its free direct or derivative use subject */ -/* to acknowledgment of its origin and compliance with any conditions */ -/* that the originators of the algorithm place on its exploitation. */ -/* */ -/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ - -/* Timing data for Rijndael (rijndael.c) - -Algorithm: rijndael (rijndael.c) - -128 bit key: -Key Setup: 305/1389 cycles (encrypt/decrypt) -Encrypt: 374 cycles = 68.4 mbits/sec -Decrypt: 352 cycles = 72.7 mbits/sec -Mean: 363 cycles = 70.5 mbits/sec - -192 bit key: -Key Setup: 277/1595 cycles (encrypt/decrypt) -Encrypt: 439 cycles = 58.3 mbits/sec -Decrypt: 425 cycles = 60.2 mbits/sec -Mean: 432 cycles = 59.3 mbits/sec - -256 bit key: -Key Setup: 374/1960 cycles (encrypt/decrypt) -Encrypt: 502 cycles = 51.0 mbits/sec -Decrypt: 498 cycles = 51.4 mbits/sec -Mean: 500 cycles = 51.2 mbits/sec +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ +#include "includes.h" -*/ +#include +#include -#include #include "rijndael.h" -void gen_tabs __P((void)); - -/* 3. Basic macros for speeding up generic operations */ - -/* Circular rotate of 32 bit values */ - -#define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) -#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) - -/* Invert byte order in a 32 bit variable */ - -#define bswap(x) ((rotl(x, 8) & 0x00ff00ff) | (rotr(x, 8) & 0xff00ff00)) - -/* Extract byte from a 32 bit quantity (little endian notation) */ - -#define byte(x,n) ((u1byte)((x) >> (8 * n))) - -#if BYTE_ORDER != LITTLE_ENDIAN -#define BYTE_SWAP -#endif - -#ifdef BYTE_SWAP -#define io_swap(x) bswap(x) -#else -#define io_swap(x) (x) -#endif - -#define LARGE_TABLES - -u1byte pow_tab[256]; -u1byte log_tab[256]; -u1byte sbx_tab[256]; -u1byte isb_tab[256]; -u4byte rco_tab[ 10]; -u4byte ft_tab[4][256]; -u4byte it_tab[4][256]; - -#ifdef LARGE_TABLES - u4byte fl_tab[4][256]; - u4byte il_tab[4][256]; -#endif - -u4byte tab_gen = 0; - -#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0) - -#define f_rn(bo, bi, n, k) \ - bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ - ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ - ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ - ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) - -#define i_rn(bo, bi, n, k) \ - bo[n] = it_tab[0][byte(bi[n],0)] ^ \ - it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ - it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ - it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) - -#ifdef LARGE_TABLES - -#define ls_box(x) \ - ( fl_tab[0][byte(x, 0)] ^ \ - fl_tab[1][byte(x, 1)] ^ \ - fl_tab[2][byte(x, 2)] ^ \ - fl_tab[3][byte(x, 3)] ) - -#define f_rl(bo, bi, n, k) \ - bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ - fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ - fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ - fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) - -#define i_rl(bo, bi, n, k) \ - bo[n] = il_tab[0][byte(bi[n],0)] ^ \ - il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ - il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ - il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) - -#else +#define FULL_UNROLL -#define ls_box(x) \ - ((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \ - ((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \ - ((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \ - ((u4byte)sbx_tab[byte(x, 3)] << 24) - -#define f_rl(bo, bi, n, k) \ - bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ \ - rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \ - rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ - rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n) - -#define i_rl(bo, bi, n, k) \ - bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ \ - rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \ - rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ - rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n) - -#endif - -void -gen_tabs(void) -{ - u4byte i, t; - u1byte p, q; - - /* log and power tables for GF(2**8) finite field with */ - /* 0x11b as modular polynomial - the simplest prmitive */ - /* root is 0x11, used here to generate the tables */ - - for(i = 0,p = 1; i < 256; ++i) { - pow_tab[i] = (u1byte)p; log_tab[p] = (u1byte)i; - - p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0); - } - - log_tab[1] = 0; p = 1; - - for(i = 0; i < 10; ++i) { - rco_tab[i] = p; +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ - p = (p << 1) ^ (p & 0x80 ? 0x1b : 0); +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { + int i = 0; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } } - - /* note that the affine byte transformation matrix in */ - /* rijndael specification is in big endian format with */ - /* bit 0 as the most significant bit. In the remainder */ - /* of the specification the bits are numbered from the */ - /* least significant end of a byte. */ - - for(i = 0; i < 256; ++i) { - p = (i ? pow_tab[255 - log_tab[i]] : 0); q = p; - q = (q >> 7) | (q << 1); p ^= q; - q = (q >> 7) | (q << 1); p ^= q; - q = (q >> 7) | (q << 1); p ^= q; - q = (q >> 7) | (q << 1); p ^= q ^ 0x63; - sbx_tab[i] = (u1byte)p; isb_tab[p] = (u1byte)i; + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBits == 192) { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } } - - for(i = 0; i < 256; ++i) { - p = sbx_tab[i]; - -#ifdef LARGE_TABLES - - t = p; fl_tab[0][i] = t; - fl_tab[1][i] = rotl(t, 8); - fl_tab[2][i] = rotl(t, 16); - fl_tab[3][i] = rotl(t, 24); -#endif - t = ((u4byte)ff_mult(2, p)) | - ((u4byte)p << 8) | - ((u4byte)p << 16) | - ((u4byte)ff_mult(3, p) << 24); - - ft_tab[0][i] = t; - ft_tab[1][i] = rotl(t, 8); - ft_tab[2][i] = rotl(t, 16); - ft_tab[3][i] = rotl(t, 24); - - p = isb_tab[i]; - -#ifdef LARGE_TABLES - - t = p; il_tab[0][i] = t; - il_tab[1][i] = rotl(t, 8); - il_tab[2][i] = rotl(t, 16); - il_tab[3][i] = rotl(t, 24); -#endif - t = ((u4byte)ff_mult(14, p)) | - ((u4byte)ff_mult( 9, p) << 8) | - ((u4byte)ff_mult(13, p) << 16) | - ((u4byte)ff_mult(11, p) << 24); - - it_tab[0][i] = t; - it_tab[1][i] = rotl(t, 8); - it_tab[2][i] = rotl(t, 16); - it_tab[3][i] = rotl(t, 24); + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBits == 256) { + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } } - - tab_gen = 1; + return 0; } -#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) - -#define imix_col(y,x) \ - u = star_x(x); \ - v = star_x(u); \ - w = star_x(v); \ - t = w ^ (x); \ - (y) = u ^ v ^ w; \ - (y) ^= rotr(u ^ t, 8) ^ \ - rotr(v ^ t, 16) ^ \ - rotr(t,24) - -/* initialise the key schedule from the user supplied key */ - -#define loop4(i) \ -{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ - t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \ - t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \ - t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \ - t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \ +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +static int +rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, + int have_encrypt) { + int Nr, i, j; + u32 temp; + + if (have_encrypt) { + Nr = have_encrypt; + } else { + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + } + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + return Nr; } -#define loop6(i) \ -{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ - t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \ - t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \ - t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \ - t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \ - t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \ - t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \ -} +static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } -#define loop8(i) \ -{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ - t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \ - t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \ - t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \ - t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \ - t = e_key[8 * i + 4] ^ ls_box(t); \ - e_key[8 * i + 12] = t; \ - t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \ - t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \ - t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \ + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); } -rijndael_ctx * -rijndael_set_key(rijndael_ctx *ctx, const u4byte *in_key, const u4byte key_len, - int encrypt) -{ - u4byte i, t, u, v, w; - u4byte *e_key = ctx->e_key; - u4byte *d_key = ctx->d_key; - - ctx->decrypt = !encrypt; - - if(!tab_gen) - gen_tabs(); - - ctx->k_len = (key_len + 31) / 32; - - e_key[0] = io_swap(in_key[0]); e_key[1] = io_swap(in_key[1]); - e_key[2] = io_swap(in_key[2]); e_key[3] = io_swap(in_key[3]); - - switch(ctx->k_len) { - case 4: t = e_key[3]; - for(i = 0; i < 10; ++i) - loop4(i); - break; - - case 6: e_key[4] = io_swap(in_key[4]); t = e_key[5] = io_swap(in_key[5]); - for(i = 0; i < 8; ++i) - loop6(i); - break; - - case 8: e_key[4] = io_swap(in_key[4]); e_key[5] = io_swap(in_key[5]); - e_key[6] = io_swap(in_key[6]); t = e_key[7] = io_swap(in_key[7]); - for(i = 0; i < 7; ++i) - loop8(i); - break; +static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; } - - if (!encrypt) { - d_key[0] = e_key[0]; d_key[1] = e_key[1]; - d_key[2] = e_key[2]; d_key[3] = e_key[3]; - - for(i = 4; i < 4 * ctx->k_len + 24; ++i) { - imix_col(d_key[i], e_key[i]); - } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; } - return ctx; + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(pt , s0); + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(pt + 4, s1); + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(pt + 8, s2); + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(pt + 12, s3); } -/* encrypt a block of text */ - -#define f_nround(bo, bi, k) \ - f_rn(bo, bi, 0, k); \ - f_rn(bo, bi, 1, k); \ - f_rn(bo, bi, 2, k); \ - f_rn(bo, bi, 3, k); \ - k += 4 - -#define f_lround(bo, bi, k) \ - f_rl(bo, bi, 0, k); \ - f_rl(bo, bi, 1, k); \ - f_rl(bo, bi, 2, k); \ - f_rl(bo, bi, 3, k) - void -rijndael_encrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk) +rijndael_set_key(rijndael_ctx *ctx, u_char *key, int bits, int encrypt) { - u4byte k_len = ctx->k_len; - u4byte *e_key = ctx->e_key; - u4byte b0[4], b1[4], *kp; - - b0[0] = io_swap(in_blk[0]) ^ e_key[0]; - b0[1] = io_swap(in_blk[1]) ^ e_key[1]; - b0[2] = io_swap(in_blk[2]) ^ e_key[2]; - b0[3] = io_swap(in_blk[3]) ^ e_key[3]; - - kp = e_key + 4; - - if(k_len > 6) { - f_nround(b1, b0, kp); f_nround(b0, b1, kp); + ctx->Nr = rijndaelKeySetupEnc(ctx->ek, key, bits); + if (encrypt) { + ctx->decrypt = 0; + memset(ctx->dk, 0, sizeof(ctx->dk)); + } else { + ctx->decrypt = 1; + memcpy(ctx->dk, ctx->ek, sizeof(ctx->ek)); + rijndaelKeySetupDec(ctx->dk, key, bits, ctx->Nr); } - - if(k_len > 4) { - f_nround(b1, b0, kp); f_nround(b0, b1, kp); - } - - f_nround(b1, b0, kp); f_nround(b0, b1, kp); - f_nround(b1, b0, kp); f_nround(b0, b1, kp); - f_nround(b1, b0, kp); f_nround(b0, b1, kp); - f_nround(b1, b0, kp); f_nround(b0, b1, kp); - f_nround(b1, b0, kp); f_lround(b0, b1, kp); - - out_blk[0] = io_swap(b0[0]); out_blk[1] = io_swap(b0[1]); - out_blk[2] = io_swap(b0[2]); out_blk[3] = io_swap(b0[3]); } -/* decrypt a block of text */ - -#define i_nround(bo, bi, k) \ - i_rn(bo, bi, 0, k); \ - i_rn(bo, bi, 1, k); \ - i_rn(bo, bi, 2, k); \ - i_rn(bo, bi, 3, k); \ - k -= 4 - -#define i_lround(bo, bi, k) \ - i_rl(bo, bi, 0, k); \ - i_rl(bo, bi, 1, k); \ - i_rl(bo, bi, 2, k); \ - i_rl(bo, bi, 3, k) - void -rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk) +rijndael_decrypt(rijndael_ctx *ctx, u_char *src, u_char *dst) { - u4byte b0[4], b1[4], *kp; - u4byte k_len = ctx->k_len; - u4byte *e_key = ctx->e_key; - u4byte *d_key = ctx->d_key; - - b0[0] = io_swap(in_blk[0]) ^ e_key[4 * k_len + 24]; - b0[1] = io_swap(in_blk[1]) ^ e_key[4 * k_len + 25]; - b0[2] = io_swap(in_blk[2]) ^ e_key[4 * k_len + 26]; - b0[3] = io_swap(in_blk[3]) ^ e_key[4 * k_len + 27]; - - kp = d_key + 4 * (k_len + 5); - - if(k_len > 6) { - i_nround(b1, b0, kp); i_nround(b0, b1, kp); - } - - if(k_len > 4) { - i_nround(b1, b0, kp); i_nround(b0, b1, kp); - } - - i_nround(b1, b0, kp); i_nround(b0, b1, kp); - i_nround(b1, b0, kp); i_nround(b0, b1, kp); - i_nround(b1, b0, kp); i_nround(b0, b1, kp); - i_nround(b1, b0, kp); i_nround(b0, b1, kp); - i_nround(b1, b0, kp); i_lround(b0, b1, kp); + rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); +} - out_blk[0] = io_swap(b0[0]); out_blk[1] = io_swap(b0[1]); - out_blk[2] = io_swap(b0[2]); out_blk[3] = io_swap(b0[3]); +void +rijndael_encrypt(rijndael_ctx *ctx, u_char *src, u_char *dst) +{ + rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); } Index: src/crypto/openssh/rijndael.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/rijndael.h,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 rijndael.h --- src/crypto/openssh/rijndael.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/rijndael.h 30 Jun 2002 11:38:00 -0000 @@ -1,47 +1,51 @@ -/* $OpenBSD: rijndael.h,v 1.7 2001/03/01 03:38:33 deraadt Exp $ */ +/* $OpenBSD: rijndael.h,v 1.12 2001/12/19 07:18:56 deraadt Exp $ */ -/* This is an independent implementation of the encryption algorithm: */ -/* */ -/* RIJNDAEL by Joan Daemen and Vincent Rijmen */ -/* */ -/* which is a candidate algorithm in the Advanced Encryption Standard */ -/* programme of the US National Institute of Standards and Technology. */ -/* */ -/* Copyright in this implementation is held by Dr B R Gladman but I */ -/* hereby give permission for its free direct or derivative use subject */ -/* to acknowledgment of its origin and compliance with any conditions */ -/* that the originators of the algorithm place on its exploitation. */ -/* */ -/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ - -#ifndef _RIJNDAEL_H_ -#define _RIJNDAEL_H_ - -/* 1. Standard types for AES cryptography source code */ - -typedef u_int8_t u1byte; /* an 8 bit unsigned character type */ -typedef u_int16_t u2byte; /* a 16 bit unsigned integer type */ -typedef u_int32_t u4byte; /* a 32 bit unsigned integer type */ - -typedef int8_t s1byte; /* an 8 bit signed character type */ -typedef int16_t s2byte; /* a 16 bit signed integer type */ -typedef int32_t s4byte; /* a 32 bit signed integer type */ - -typedef struct _rijndael_ctx { - u4byte k_len; - int decrypt; - u4byte e_key[64]; - u4byte d_key[64]; +/** + * rijndael-alg-fst.h + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ +#ifndef __RIJNDAEL_H +#define __RIJNDAEL_H + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +/* The structure for key information */ +typedef struct { + int decrypt; + int Nr; /* key-length-dependent number of rounds */ + u32 ek[4*(MAXNR + 1)]; /* encrypt key schedule */ + u32 dk[4*(MAXNR + 1)]; /* decrypt key schedule */ } rijndael_ctx; +void rijndael_set_key(rijndael_ctx *, u_char *, int, int); +void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); +void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); -/* 2. Standard interface for AES cryptographic routines */ - -/* These are all based on 32 bit unsigned values and will therefore */ -/* require endian conversions for big-endian architectures */ - -rijndael_ctx *rijndael_set_key __P((rijndael_ctx *, const u4byte *, u4byte, int)); -void rijndael_encrypt __P((rijndael_ctx *, const u4byte *, u4byte *)); -void rijndael_decrypt __P((rijndael_ctx *, const u4byte *, u4byte *)); - -#endif /* _RIJNDAEL_H_ */ +#endif /* __RIJNDAEL_H */ Index: src/crypto/openssh/rsa.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/rsa.c,v retrieving revision 1.1.1.1.2.7 diff -u -u -r1.1.1.1.2.7 rsa.c --- src/crypto/openssh/rsa.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.7 +++ src/crypto/openssh/rsa.c 30 Jun 2002 11:38:00 -0000 @@ -60,8 +60,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: rsa.c,v 1.22 2001/03/26 23:23:23 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/rsa.c,v 1.1.1.1.2.7 2001/09/28 01:33:34 green Exp $"); +RCSID("$OpenBSD: rsa.c,v 1.24 2001/12/27 18:22:16 markus Exp $"); #include "rsa.h" #include "log.h" @@ -121,14 +120,17 @@ return len; } +/* calculate p-1 and q-1 */ void -generate_additional_parameters(RSA *rsa) +rsa_generate_additional_parameters(RSA *rsa) { BIGNUM *aux; BN_CTX *ctx; - /* Generate additional parameters */ - aux = BN_new(); - ctx = BN_CTX_new(); + + if ((aux = BN_new()) == NULL) + fatal("rsa_generate_additional_parameters: BN_new failed"); + if ((ctx = BN_CTX_new()) == NULL) + fatal("rsa_generate_additional_parameters: BN_CTX_new failed"); BN_sub(aux, rsa->q, BN_value_one()); BN_mod(rsa->dmq1, rsa->d, aux, ctx); Index: src/crypto/openssh/rsa.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/rsa.h,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 rsa.h --- src/crypto/openssh/rsa.h 28 Sep 2001 01:33:34 -0000 1.2.2.4 +++ src/crypto/openssh/rsa.h 30 Jun 2002 11:38:00 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: rsa.h,v 1.15 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,18 +13,14 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: rsa.h,v 1.11 2001/03/26 23:23:24 markus Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/rsa.h,v 1.2.2.4 2001/09/28 01:33:34 green Exp $"); */ - #ifndef RSA_H #define RSA_H #include #include -void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); -int rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); - -void generate_additional_parameters __P((RSA *rsa)); +void rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); +int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); +void rsa_generate_additional_parameters(RSA *); #endif /* RSA_H */ Index: src/crypto/openssh/scard-opensc.c =================================================================== RCS file: src/crypto/openssh/scard-opensc.c diff -N src/crypto/openssh/scard-opensc.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/scard-opensc.c 30 Jun 2002 11:38:00 -0000 @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2002 Juha Yrjölä. All rights reserved. + * Copyright (c) 2001 Markus Friedl. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#if defined(SMARTCARD) && defined(USE_OPENSC) + +#include +#include + +#include +#include + +#include "key.h" +#include "log.h" +#include "xmalloc.h" +#include "readpass.h" +#include "scard.h" + +#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE) +#define USE_ENGINE +#define RSA_get_default_method RSA_get_default_openssl_method +#else +#endif + +#ifdef USE_ENGINE +#include +#define sc_get_rsa sc_get_engine +#else +#define sc_get_rsa sc_get_rsa_method +#endif + +static int sc_reader_id; +static sc_context_t *ctx = NULL; +static sc_card_t *card = NULL; +static sc_pkcs15_card_t *p15card = NULL; + +static char *sc_pin = NULL; + +struct sc_priv_data +{ + struct sc_pkcs15_id cert_id; + int ref_count; +}; + +void +sc_close(void) +{ + if (p15card) { + sc_pkcs15_unbind(p15card); + p15card = NULL; + } + if (card) { + sc_disconnect_card(card, 0); + card = NULL; + } + if (ctx) { + sc_release_context(ctx); + ctx = NULL; + } +} + +static int +sc_init(void) +{ + int r; + + r = sc_establish_context(&ctx, "openssh"); + if (r) + goto err; + r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card); + if (r) + goto err; + r = sc_pkcs15_bind(card, &p15card); + if (r) + goto err; + return 0; +err: + sc_close(); + return r; +} + +/* private key operations */ + +static int +sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out) +{ + int r; + struct sc_priv_data *priv; + struct sc_pkcs15_object *key_obj; + struct sc_pkcs15_prkey_info *key; + struct sc_pkcs15_object *pin_obj; + struct sc_pkcs15_pin_info *pin; + + priv = (struct sc_priv_data *) RSA_get_app_data(rsa); + if (priv == NULL) + return -1; + if (p15card == NULL) { + sc_close(); + r = sc_init(); + if (r) { + error("SmartCard init failed: %s", sc_strerror(r)); + goto err; + } + } + r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj); + if (r) { + error("Unable to find private key from SmartCard: %s", + sc_strerror(r)); + goto err; + } + key = key_obj->data; + r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id, + &pin_obj); + if (r) { + error("Unable to find PIN object from SmartCard: %s", + sc_strerror(r)); + goto err; + } + pin = pin_obj->data; + r = sc_lock(card); + if (r) { + error("Unable to lock smartcard: %s", sc_strerror(r)); + goto err; + } + if (sc_pin != NULL) { + r = sc_pkcs15_verify_pin(p15card, pin, sc_pin, + strlen(sc_pin)); + if (r) { + sc_unlock(card); + error("PIN code verification failed: %s", + sc_strerror(r)); + goto err; + } + } + *key_obj_out = key_obj; + return 0; +err: + sc_close(); + return -1; +} + +static int +sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, + int padding) +{ + struct sc_pkcs15_object *key_obj; + int r; + + if (padding != RSA_PKCS1_PADDING) + return -1; + r = sc_prkey_op_init(rsa, &key_obj); + if (r) + return -1; + r = sc_pkcs15_decipher(p15card, key_obj, 0, from, flen, to, flen); + sc_unlock(card); + if (r < 0) { + error("sc_pkcs15_decipher() failed: %s", sc_strerror(r)); + goto err; + } + return r; +err: + sc_close(); + return -1; +} + +static int +sc_sign(int type, u_char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, RSA *rsa) +{ + struct sc_pkcs15_object *key_obj; + int r; + unsigned long flags = 0; + + r = sc_prkey_op_init(rsa, &key_obj); + if (r) + return -1; + /* FIXME: length of sigret correct? */ + /* FIXME: check 'type' and modify flags accordingly */ + flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1; + r = sc_pkcs15_compute_signature(p15card, key_obj, flags, + m, m_len, sigret, RSA_size(rsa)); + sc_unlock(card); + if (r < 0) { + error("sc_pkcs15_compute_signature() failed: %s", + sc_strerror(r)); + goto err; + } + *siglen = r; + return 1; +err: + sc_close(); + return 0; +} + +static int +sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, + int padding) +{ + error("Private key encryption not supported"); + return -1; +} + +/* called on free */ + +static int (*orig_finish)(RSA *rsa) = NULL; + +static int +sc_finish(RSA *rsa) +{ + struct sc_priv_data *priv; + + priv = RSA_get_app_data(rsa); + priv->ref_count--; + if (priv->ref_count == 0) { + free(priv); + sc_close(); + } + if (orig_finish) + orig_finish(rsa); + return 1; +} + +/* engine for overloading private key operations */ + +static RSA_METHOD * +sc_get_rsa_method(void) +{ + static RSA_METHOD smart_rsa; + const RSA_METHOD *def = RSA_get_default_method(); + + /* use the OpenSSL version */ + memcpy(&smart_rsa, def, sizeof(smart_rsa)); + + smart_rsa.name = "opensc"; + + /* overload */ + smart_rsa.rsa_priv_enc = sc_private_encrypt; + smart_rsa.rsa_priv_dec = sc_private_decrypt; + smart_rsa.rsa_sign = sc_sign; + + /* save original */ + orig_finish = def->finish; + smart_rsa.finish = sc_finish; + + return &smart_rsa; +} + +#ifdef USE_ENGINE +static ENGINE * +sc_get_engine(void) +{ + static ENGINE *smart_engine = NULL; + + if ((smart_engine = ENGINE_new()) == NULL) + fatal("ENGINE_new failed"); + + ENGINE_set_id(smart_engine, "opensc"); + ENGINE_set_name(smart_engine, "OpenSC"); + + ENGINE_set_RSA(smart_engine, sc_get_rsa_method()); + ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method()); + ENGINE_set_DH(smart_engine, DH_get_default_openssl_method()); + ENGINE_set_RAND(smart_engine, RAND_SSLeay()); + ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp); + + return smart_engine; +} +#endif + +static void +convert_rsa_to_rsa1(Key * in, Key * out) +{ + struct sc_priv_data *priv; + + out->rsa->flags = in->rsa->flags; + out->flags = in->flags; + RSA_set_method(out->rsa, RSA_get_method(in->rsa)); + BN_copy(out->rsa->n, in->rsa->n); + BN_copy(out->rsa->e, in->rsa->e); + priv = RSA_get_app_data(in->rsa); + priv->ref_count++; + RSA_set_app_data(out->rsa, priv); + return; +} + +static int +sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj) +{ + int r; + sc_pkcs15_cert_t *cert = NULL; + struct sc_priv_data *priv = NULL; + sc_pkcs15_cert_info_t *cinfo = cert_obj->data; + + X509 *x509 = NULL; + EVP_PKEY *pubkey = NULL; + u8 *p; + char *tmp; + + debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]); + r = sc_pkcs15_read_certificate(p15card, cinfo, &cert); + if (r) { + log("Certificate read failed: %s", sc_strerror(r)); + goto err; + } + x509 = X509_new(); + if (x509 == NULL) { + r = -1; + goto err; + } + p = cert->data; + if (!d2i_X509(&x509, &p, cert->data_len)) { + log("Unable to parse X.509 certificate"); + r = -1; + goto err; + } + sc_pkcs15_free_certificate(cert); + cert = NULL; + pubkey = X509_get_pubkey(x509); + X509_free(x509); + x509 = NULL; + if (pubkey->type != EVP_PKEY_RSA) { + log("Public key is of unknown type"); + r = -1; + goto err; + } + k->rsa = EVP_PKEY_get1_RSA(pubkey); + EVP_PKEY_free(pubkey); + + k->rsa->flags |= RSA_FLAG_SIGN_VER; + RSA_set_method(k->rsa, sc_get_rsa_method()); + priv = xmalloc(sizeof(struct sc_priv_data)); + priv->cert_id = cinfo->id; + priv->ref_count = 1; + RSA_set_app_data(k->rsa, priv); + + k->flags = KEY_FLAG_EXT; + tmp = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); + debug("fingerprint %d %s", key_size(k), tmp); + xfree(tmp); + + return 0; +err: + if (cert) + sc_pkcs15_free_certificate(cert); + if (pubkey) + EVP_PKEY_free(pubkey); + if (x509) + X509_free(x509); + return r; +} + +Key ** +sc_get_keys(const char *id, const char *pin) +{ + Key *k, **keys; + int i, r, real_count = 0, key_count; + sc_pkcs15_id_t cert_id; + sc_pkcs15_object_t *certs[32]; + char *buf = xstrdup(id), *p; + + debug("sc_get_keys called: id = %s", id); + + if (sc_pin != NULL) + xfree(sc_pin); + sc_pin = (pin == NULL) ? NULL : xstrdup(pin); + + cert_id.len = 0; + if ((p = strchr(buf, ':')) != NULL) { + *p = 0; + p++; + sc_pkcs15_hex_string_to_id(p, &cert_id); + } + r = sscanf(buf, "%d", &sc_reader_id); + xfree(buf); + if (r != 1) + goto err; + if (p15card == NULL) { + sc_close(); + r = sc_init(); + if (r) { + error("Smartcard init failed: %s", sc_strerror(r)); + goto err; + } + } + if (cert_id.len) { + r = sc_pkcs15_find_cert_by_id(p15card, &cert_id, &certs[0]); + if (r < 0) + goto err; + key_count = 1; + } else { + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, + certs, 32); + if (r == 0) { + log("No certificates found on smartcard"); + r = -1; + goto err; + } else if (r < 0) { + error("Certificate enumeration failed: %s", + sc_strerror(r)); + goto err; + } + key_count = r; + } + /* FIXME: only keep entries with a corresponding private key */ + keys = xmalloc(sizeof(Key *) * (key_count*2+1)); + for (i = 0; i < key_count; i++) { + k = key_new(KEY_RSA); + if (k == NULL) + break; + r = sc_read_pubkey(k, certs[i]); + if (r) { + error("sc_read_pubkey failed: %s", sc_strerror(r)); + key_free(k); + continue; + } + keys[real_count] = k; + real_count++; + k = key_new(KEY_RSA1); + if (k == NULL) + break; + convert_rsa_to_rsa1(keys[real_count-1], k); + keys[real_count] = k; + real_count++; + } + keys[real_count] = NULL; + + return keys; +err: + sc_close(); + return NULL; +} + +int +sc_put_key(Key *prv, const char *id) +{ + error("key uploading not yet supported"); + return -1; +} + +#endif /* SMARTCARD */ Index: src/crypto/openssh/scard.c =================================================================== RCS file: src/crypto/openssh/scard.c diff -N src/crypto/openssh/scard.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/scard.c 30 Jun 2002 11:38:00 -0000 @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2001 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#if defined(SMARTCARD) && defined(USE_SECTOK) +RCSID("$OpenBSD: scard.c,v 1.26 2002/06/23 03:30:17 deraadt Exp $"); + +#include +#include + +#include "key.h" +#include "log.h" +#include "xmalloc.h" +#include "readpass.h" +#include "scard.h" + +#if OPENSSL_VERSION_NUMBER < 0x00907000L +#define USE_ENGINE +#define RSA_get_default_method RSA_get_default_openssl_method +#else +#endif + +#ifdef USE_ENGINE +#include +#define sc_get_rsa sc_get_engine +#else +#define sc_get_rsa sc_get_rsa_method +#endif + +#define CLA_SSH 0x05 +#define INS_DECRYPT 0x10 +#define INS_GET_KEYLENGTH 0x20 +#define INS_GET_PUBKEY 0x30 +#define INS_GET_RESPONSE 0xc0 + +#define MAX_BUF_SIZE 256 + +u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63}; + +static int sc_fd = -1; +static char *sc_reader_id = NULL; +static char *sc_pin = NULL; +static int cla = 0x00; /* class */ + +static void sc_mk_digest(const char *pin, u_char *digest); +static int get_AUT0(u_char *aut0); +static int try_AUT0(void); + +/* interface to libsectok */ + +static int +sc_open(void) +{ + int sw; + + if (sc_fd >= 0) + return sc_fd; + + sc_fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw); + if (sc_fd < 0) { + error("sectok_open failed: %s", sectok_get_sw(sw)); + return SCARD_ERROR_FAIL; + } + if (! sectok_cardpresent(sc_fd)) { + debug("smartcard in reader %s not present, skipping", + sc_reader_id); + sc_close(); + return SCARD_ERROR_NOCARD; + } + if (sectok_reset(sc_fd, 0, NULL, &sw) <= 0) { + error("sectok_reset failed: %s", sectok_get_sw(sw)); + sc_fd = -1; + return SCARD_ERROR_FAIL; + } + if ((cla = cyberflex_inq_class(sc_fd)) < 0) + cla = 0; + + debug("sc_open ok %d", sc_fd); + return sc_fd; +} + +static int +sc_enable_applet(void) +{ + static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e}; + int sw = 0; + + /* select applet id */ + sectok_apdu(sc_fd, cla, 0xa4, 0x04, 0, sizeof aid, aid, 0, NULL, &sw); + if (!sectok_swOK(sw)) { + error("sectok_apdu failed: %s", sectok_get_sw(sw)); + sc_close(); + return -1; + } + return 0; +} + +static int +sc_init(void) +{ + int status; + + status = sc_open(); + if (status == SCARD_ERROR_NOCARD) { + return SCARD_ERROR_NOCARD; + } + if (status < 0 ) { + error("sc_open failed"); + return status; + } + if (sc_enable_applet() < 0) { + error("sc_enable_applet failed"); + return SCARD_ERROR_APPLET; + } + return 0; +} + +static int +sc_read_pubkey(Key * k) +{ + u_char buf[2], *n; + char *p; + int len, sw, status = -1; + + len = sw = 0; + n = NULL; + + if (sc_fd < 0) { + if (sc_init() < 0) + goto err; + } + + /* get key size */ + sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL, + sizeof(buf), buf, &sw); + if (!sectok_swOK(sw)) { + error("could not obtain key length: %s", sectok_get_sw(sw)); + goto err; + } + len = (buf[0] << 8) | buf[1]; + len /= 8; + debug("INS_GET_KEYLENGTH: len %d sw %s", len, sectok_get_sw(sw)); + + n = xmalloc(len); + /* get n */ + sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw); + + if (sw == 0x6982) { + if (try_AUT0() < 0) + goto err; + sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw); + } + if (!sectok_swOK(sw)) { + error("could not obtain public key: %s", sectok_get_sw(sw)); + goto err; + } + + debug("INS_GET_KEYLENGTH: sw %s", sectok_get_sw(sw)); + + if (BN_bin2bn(n, len, k->rsa->n) == NULL) { + error("c_read_pubkey: BN_bin2bn failed"); + goto err; + } + + /* currently the java applet just stores 'n' */ + if (!BN_set_word(k->rsa->e, 35)) { + error("c_read_pubkey: BN_set_word(e, 35) failed"); + goto err; + } + + status = 0; + p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); + debug("fingerprint %u %s", key_size(k), p); + xfree(p); + +err: + if (n != NULL) + xfree(n); + sc_close(); + return status; +} + +/* private key operations */ + +static int +sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, + int padding) +{ + u_char *padded = NULL; + int sw, len, olen, status = -1; + + debug("sc_private_decrypt called"); + + olen = len = sw = 0; + if (sc_fd < 0) { + status = sc_init(); + if (status < 0 ) + goto err; + } + if (padding != RSA_PKCS1_PADDING) + goto err; + + len = BN_num_bytes(rsa->n); + padded = xmalloc(len); + + sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw); + + if (sw == 0x6982) { + if (try_AUT0() < 0) + goto err; + sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw); + } + if (!sectok_swOK(sw)) { + error("sc_private_decrypt: INS_DECRYPT failed: %s", + sectok_get_sw(sw)); + goto err; + } + olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1, + len); +err: + if (padded) + xfree(padded); + sc_close(); + return (olen >= 0 ? olen : status); +} + +static int +sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, + int padding) +{ + u_char *padded = NULL; + int sw, len, status = -1; + + len = sw = 0; + if (sc_fd < 0) { + status = sc_init(); + if (status < 0 ) + goto err; + } + if (padding != RSA_PKCS1_PADDING) + goto err; + + debug("sc_private_encrypt called"); + len = BN_num_bytes(rsa->n); + padded = xmalloc(len); + + if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) { + error("RSA_padding_add_PKCS1_type_1 failed"); + goto err; + } + sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw); + if (sw == 0x6982) { + if (try_AUT0() < 0) + goto err; + sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw); + } + if (!sectok_swOK(sw)) { + error("sc_private_encrypt: INS_DECRYPT failed: %s", + sectok_get_sw(sw)); + goto err; + } +err: + if (padded) + xfree(padded); + sc_close(); + return (len >= 0 ? len : status); +} + +/* called on free */ + +static int (*orig_finish)(RSA *rsa) = NULL; + +static int +sc_finish(RSA *rsa) +{ + if (orig_finish) + orig_finish(rsa); + sc_close(); + return 1; +} + +/* engine for overloading private key operations */ + +static RSA_METHOD * +sc_get_rsa_method(void) +{ + static RSA_METHOD smart_rsa; + const RSA_METHOD *def = RSA_get_default_method(); + + /* use the OpenSSL version */ + memcpy(&smart_rsa, def, sizeof(smart_rsa)); + + smart_rsa.name = "sectok"; + + /* overload */ + smart_rsa.rsa_priv_enc = sc_private_encrypt; + smart_rsa.rsa_priv_dec = sc_private_decrypt; + + /* save original */ + orig_finish = def->finish; + smart_rsa.finish = sc_finish; + + return &smart_rsa; +} + +#ifdef USE_ENGINE +static ENGINE * +sc_get_engine(void) +{ + static ENGINE *smart_engine = NULL; + + if ((smart_engine = ENGINE_new()) == NULL) + fatal("ENGINE_new failed"); + + ENGINE_set_id(smart_engine, "sectok"); + ENGINE_set_name(smart_engine, "libsectok"); + + ENGINE_set_RSA(smart_engine, sc_get_rsa_method()); + ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method()); + ENGINE_set_DH(smart_engine, DH_get_default_openssl_method()); + ENGINE_set_RAND(smart_engine, RAND_SSLeay()); + ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp); + + return smart_engine; +} +#endif + +void +sc_close(void) +{ + if (sc_fd >= 0) { + sectok_close(sc_fd); + sc_fd = -1; + } +} + +Key ** +sc_get_keys(const char *id, const char *pin) +{ + Key *k, *n, **keys; + int status, nkeys = 2; + + if (sc_reader_id != NULL) + xfree(sc_reader_id); + sc_reader_id = xstrdup(id); + + if (sc_pin != NULL) + xfree(sc_pin); + sc_pin = (pin == NULL) ? NULL : xstrdup(pin); + + k = key_new(KEY_RSA); + if (k == NULL) { + return NULL; + } + status = sc_read_pubkey(k); + if (status == SCARD_ERROR_NOCARD) { + key_free(k); + return NULL; + } + if (status < 0 ) { + error("sc_read_pubkey failed"); + key_free(k); + return NULL; + } + keys = xmalloc((nkeys+1) * sizeof(Key *)); + + n = key_new(KEY_RSA1); + BN_copy(n->rsa->n, k->rsa->n); + BN_copy(n->rsa->e, k->rsa->e); + RSA_set_method(n->rsa, sc_get_rsa()); + n->flags |= KEY_FLAG_EXT; + keys[0] = n; + + n = key_new(KEY_RSA); + BN_copy(n->rsa->n, k->rsa->n); + BN_copy(n->rsa->e, k->rsa->e); + RSA_set_method(n->rsa, sc_get_rsa()); + n->flags |= KEY_FLAG_EXT; + keys[1] = n; + + keys[2] = NULL; + + key_free(k); + return keys; +} + +#define NUM_RSA_KEY_ELEMENTS 5+1 +#define COPY_RSA_KEY(x, i) \ + do { \ + len = BN_num_bytes(prv->rsa->x); \ + elements[i] = xmalloc(len); \ + debug("#bytes %d", len); \ + if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \ + goto done; \ + } while (0) + +static void +sc_mk_digest(const char *pin, u_char *digest) +{ + const EVP_MD *evp_md = EVP_sha1(); + EVP_MD_CTX md; + + EVP_DigestInit(&md, evp_md); + EVP_DigestUpdate(&md, pin, strlen(pin)); + EVP_DigestFinal(&md, digest, NULL); +} + +static int +get_AUT0(u_char *aut0) +{ + char *pass; + + pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN); + if (pass == NULL) + return -1; + if (!strcmp(pass, "-")) { + memcpy(aut0, DEFAUT0, sizeof DEFAUT0); + return 0; + } + sc_mk_digest(pass, aut0); + memset(pass, 0, strlen(pass)); + xfree(pass); + return 0; +} + +static int +try_AUT0(void) +{ + u_char aut0[EVP_MAX_MD_SIZE]; + + /* permission denied; try PIN if provided */ + if (sc_pin && strlen(sc_pin) > 0) { + sc_mk_digest(sc_pin, aut0); + if (cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) { + error("smartcard passphrase incorrect"); + return (-1); + } + } else { + /* try default AUT0 key */ + if (cyberflex_verify_AUT0(sc_fd, cla, DEFAUT0, 8) < 0) { + /* default AUT0 key failed; prompt for passphrase */ + if (get_AUT0(aut0) < 0 || + cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) { + error("smartcard passphrase incorrect"); + return (-1); + } + } + } + return (0); +} + +int +sc_put_key(Key *prv, const char *id) +{ + u_char *elements[NUM_RSA_KEY_ELEMENTS]; + u_char key_fid[2]; + u_char AUT0[EVP_MAX_MD_SIZE]; + int len, status = -1, i, fd = -1, ret; + int sw = 0, cla = 0x00; + + for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) + elements[i] = NULL; + + COPY_RSA_KEY(q, 0); + COPY_RSA_KEY(p, 1); + COPY_RSA_KEY(iqmp, 2); + COPY_RSA_KEY(dmq1, 3); + COPY_RSA_KEY(dmp1, 4); + COPY_RSA_KEY(n, 5); + len = BN_num_bytes(prv->rsa->n); + fd = sectok_friendly_open(id, STONOWAIT, &sw); + if (fd < 0) { + error("sectok_open failed: %s", sectok_get_sw(sw)); + goto done; + } + if (! sectok_cardpresent(fd)) { + error("smartcard in reader %s not present", id); + goto done; + } + ret = sectok_reset(fd, 0, NULL, &sw); + if (ret <= 0) { + error("sectok_reset failed: %s", sectok_get_sw(sw)); + goto done; + } + if ((cla = cyberflex_inq_class(fd)) < 0) { + error("cyberflex_inq_class failed"); + goto done; + } + memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0)); + if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { + if (get_AUT0(AUT0) < 0 || + cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { + memset(AUT0, 0, sizeof(DEFAUT0)); + error("smartcard passphrase incorrect"); + goto done; + } + } + memset(AUT0, 0, sizeof(DEFAUT0)); + key_fid[0] = 0x00; + key_fid[1] = 0x12; + if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements, + &sw) < 0) { + error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw)); + goto done; + } + if (!sectok_swOK(sw)) + goto done; + log("cyberflex_load_rsa_priv done"); + key_fid[0] = 0x73; + key_fid[1] = 0x68; + if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5], + &sw) < 0) { + error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw)); + goto done; + } + if (!sectok_swOK(sw)) + goto done; + log("cyberflex_load_rsa_pub done"); + status = 0; + +done: + memset(elements[0], '\0', BN_num_bytes(prv->rsa->q)); + memset(elements[1], '\0', BN_num_bytes(prv->rsa->p)); + memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp)); + memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1)); + memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1)); + memset(elements[5], '\0', BN_num_bytes(prv->rsa->n)); + + for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++) + if (elements[i]) + xfree(elements[i]); + if (fd != -1) + sectok_close(fd); + return (status); +} +#endif /* SMARTCARD && USE_SECTOK */ Index: src/crypto/openssh/scard.h =================================================================== RCS file: src/crypto/openssh/scard.h diff -N src/crypto/openssh/scard.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/scard.h 30 Jun 2002 11:38:00 -0000 @@ -0,0 +1,40 @@ +/* $OpenBSD: scard.h,v 1.10 2002/03/25 17:34:27 markus Exp $ */ + +/* + * Copyright (c) 2001 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SCARD_H +#define SCARD_H + +#include "key.h" + +#define SCARD_ERROR_FAIL -1 +#define SCARD_ERROR_NOCARD -2 +#define SCARD_ERROR_APPLET -3 + +Key **sc_get_keys(const char*, const char*); +void sc_close(void); +int sc_put_key(Key *, const char*); + +#endif Index: src/crypto/openssh/scp-common.c =================================================================== RCS file: src/crypto/openssh/scp-common.c diff -N src/crypto/openssh/scp-common.c --- src/crypto/openssh/scp-common.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,98 +0,0 @@ -/* - * Copyright (c) 1999 Theo de Raadt. All rights reserved. - * Copyright (c) 1999 Aaron Campbell. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Parts from: - * - * 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. - * - */ - -#include "includes.h" -RCSID("$OpenBSD: scp-common.c,v 1.1 2001/04/16 02:31:43 mouring Exp $"); - -char * -cleanhostname(host) - char *host; -{ - if (*host == '[' && host[strlen(host) - 1] == ']') { - host[strlen(host) - 1] = '\0'; - return (host + 1); - } else - return host; -} - -char * -colon(cp) - char *cp; -{ - int flag = 0; - - if (*cp == ':') /* Leading colon is part of file name. */ - return (0); - if (*cp == '[') - flag = 1; - - for (; *cp; ++cp) { - if (*cp == '@' && *(cp+1) == '[') - flag = 1; - if (*cp == ']' && *(cp+1) == ':' && flag) - return (cp+1); - if (*cp == ':' && !flag) - return (cp); - if (*cp == '/') - return (0); - } - return (0); -} Index: src/crypto/openssh/scp-common.h =================================================================== RCS file: src/crypto/openssh/scp-common.h diff -N src/crypto/openssh/scp-common.h --- src/crypto/openssh/scp-common.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,64 +0,0 @@ -/* $OpenBSD: scp-common.h,v 1.1 2001/04/16 02:31:43 mouring Exp $ */ -/* - * Copyright (c) 1999 Theo de Raadt. All rights reserved. - * Copyright (c) 1999 Aaron Campbell. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Parts from: - * - * 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. - * - */ - -char *cleanhostname(char *host); -char *colon(char *cp); Index: src/crypto/openssh/scp.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/scp.1,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 scp.1 --- src/crypto/openssh/scp.1 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/scp.1 30 Jun 2002 11:38:00 -0000 @@ -9,7 +9,7 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.14 2001/02/04 11:11:53 djm Exp $ +.\" $OpenBSD: scp.1,v 1.23 2002/06/22 16:41:57 stevesk Exp $ .\" .Dd September 25, 1999 .Dt SCP 1 @@ -19,12 +19,13 @@ .Nd secure copy (remote file copy program) .Sh SYNOPSIS .Nm scp -.Op Fl pqrvC46 +.Op Fl pqrvBC46 +.Op Fl F Ar ssh_config .Op Fl S Ar program .Op Fl P Ar port .Op Fl c Ar cipher .Op Fl i Ar identity_file -.Op Fl o Ar option +.Op Fl o Ar ssh_option .Sm off .Oo .Op Ar user@ @@ -92,6 +93,12 @@ flag to .Xr ssh 1 to enable compression. +.It Fl F Ar ssh_config +Specifies an alternative +per-user configuration file for +.Nm ssh . +This option is directly passed to +.Xr ssh 1 . .It Fl P Ar port Specifies the port to connect to on the remote host. Note that this option is written with a capital @@ -107,9 +114,17 @@ The program must understand .Xr ssh 1 options. -.It Fl o Ar option -The given option is directly passed to -.Xr ssh 1 . +.It Fl o Ar ssh_option +Can be used to pass options to +.Nm ssh +in the format used in +.Xr ssh_config 5 . +This is useful for specifying options +for which there is no separate +.Nm scp +command-line flag. For example, forcing the use of protocol +version 1 is specified using +.Ic scp -oProtocol=1 . .It Fl 4 Forces .Nm @@ -119,6 +134,9 @@ .Nm to use IPv6 addresses only. .El +.Sh DIAGNOSTICS +.Nm +exits with 0 on success or >0 if an error occurred. .Sh AUTHORS Timo Rinne and Tatu Ylonen .Sh HISTORY @@ -134,4 +152,5 @@ .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 , +.Xr ssh_config 5 , .Xr sshd 8 Index: src/crypto/openssh/scp.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/scp.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 scp.c --- src/crypto/openssh/scp.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/scp.c 30 Jun 2002 11:38:00 -0000 @@ -75,16 +75,24 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.68 2001/04/22 12:34:05 markus Exp $"); +RCSID("$OpenBSD: scp.c,v 1.91 2002/06/19 00:27:55 deraadt Exp $"); #include "xmalloc.h" #include "atomicio.h" #include "pathnames.h" #include "log.h" -#include "scp-common.h" +#include "misc.h" + +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif /* For progressmeter() -- number of seconds before xfer considered "stalled" */ #define STALLTIME 5 +/* alarm() interval for updating progress meter */ +#define PROGRESSTIME 1 /* Visual statistics about files as they are transferred. */ void progressmeter(int); @@ -93,8 +101,8 @@ int getttywidth(void); int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); -/* setup arguments for the call to ssh */ -void addargs(char *fmt, ...) __attribute__((format(printf, 1, 2))); +/* Struct for addargs */ +arglist args; /* Time a transfer started. */ static struct timeval start; @@ -117,13 +125,6 @@ /* This is the program to execute for the secured connection. ("ssh" or -S) */ char *ssh_program = _PATH_SSH_PROGRAM; -/* This is the list of arguments that scp passes to ssh */ -struct { - char **list; - int num; - int nalloc; -} args; - /* * This function executes the given command as the specified user on the * given host. This returns < 0 if execution fails, and >= 0 otherwise. This @@ -136,8 +137,10 @@ int pin[2], pout[2], reserved[2]; if (verbose_mode) - fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", - ssh_program, host, remuser ? remuser : "(unspecified)", cmd); + fprintf(stderr, + "Executing: program %s host %s, user %s, command %s\n", + ssh_program, host, + remuser ? remuser : "(unspecified)", cmd); /* * Reserve two descriptors so that the real pipes won't get @@ -167,9 +170,9 @@ args.list[0] = ssh_program; if (remuser != NULL) - addargs("-l%s", remuser); - addargs("%s", host); - addargs("%s", cmd); + addargs(&args, "-l%s", remuser); + addargs(&args, "%s", host); + addargs(&args, "%s", cmd); execvp(ssh_program, args.list); perror(ssh_program); @@ -221,30 +224,34 @@ extern char *optarg; extern int optind; + __progname = get_progname(argv[0]); + args.list = NULL; - addargs("ssh"); /* overwritten with ssh_program */ - addargs("-x"); - addargs("-oFallBackToRsh no"); + addargs(&args, "ssh"); /* overwritten with ssh_program */ + addargs(&args, "-x"); + addargs(&args, "-oForwardAgent no"); + addargs(&args, "-oClearAllForwardings yes"); fflag = tflag = 0; - while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:")) != -1) + while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) switch (ch) { /* User-visible flags. */ case '4': case '6': case 'C': - addargs("-%c", ch); + addargs(&args, "-%c", ch); break; case 'o': case 'c': case 'i': - addargs("-%c%s", ch, optarg); + case 'F': + addargs(&args, "-%c%s", ch, optarg); break; case 'P': - addargs("-p%s", optarg); + addargs(&args, "-p%s", optarg); break; case 'B': - addargs("-oBatchmode yes"); + addargs(&args, "-oBatchmode yes"); break; case 'p': pflag = 1; @@ -256,6 +263,7 @@ ssh_program = xstrdup(optarg); break; case 'v': + addargs(&args, "-v"); verbose_mode = 1; break; case 'q': @@ -273,6 +281,9 @@ case 't': /* "to" */ iamremote = 1; tflag = 1; +#ifdef HAVE_CYGWIN + setmode(0, O_BINARY); +#endif break; default: usage(); @@ -352,13 +363,16 @@ for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src) { /* remote to remote */ + static char *ssh_options = + "-x -o'ClearAllForwardings yes'"; *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; + strlen(thost) + strlen(targ) + + strlen(ssh_options) + CMDNEEDS + 20; bp = xmalloc(len); if (host) { *host++ = 0; @@ -369,19 +383,19 @@ else if (!okname(suser)) continue; snprintf(bp, len, - "%s%s -x -o'FallBackToRsh no' -n " + "%s%s %s -n " "-l %s %s %s %s '%s%s%s:%s'", ssh_program, verbose_mode ? " -v" : "", - suser, host, cmd, src, + ssh_options, suser, host, cmd, src, tuser ? tuser : "", tuser ? "@" : "", thost, targ); } else { host = cleanhostname(argv[i]); snprintf(bp, len, - "exec %s%s -x -o'FallBackToRsh no' -n %s " + "exec %s%s %s -n %s " "%s %s '%s%s%s:%s'", ssh_program, verbose_mode ? " -v" : "", - host, cmd, src, + ssh_options, host, cmd, src, tuser ? tuser : "", tuser ? "@" : "", thost, targ); } @@ -479,6 +493,11 @@ len = strlen(name); while (len > 1 && name[len-1] == '/') name[--len] = '\0'; + if (strchr(name, '\n') != NULL) { + run_err("%s: skipping, filename contains a newline", + name); + goto next; + } if ((fd = open(name, O_RDONLY, 0)) < 0) goto syserr; if (fstat(fd, &stb) < 0) { @@ -516,9 +535,16 @@ goto next; } #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) +#ifdef HAVE_LONG_LONG_INT snprintf(buf, sizeof buf, "C%04o %lld %s\n", (u_int) (stb.st_mode & FILEMODEMASK), (long long)stb.st_size, last); +#else + /* XXX: Handle integer overflow? */ + snprintf(buf, sizeof buf, "C%04o %lu %s\n", + (u_int) (stb.st_mode & FILEMODEMASK), + (u_long) stb.st_size, last); +#endif if (verbose_mode) { fprintf(stderr, "Sending file modes: %s", buf); fflush(stderr); @@ -641,7 +667,7 @@ #define atime tv[0] #define mtime tv[1] -#define SCREWUP(str) { why = str; goto screwup; } +#define SCREWUP(str) do { why = str; goto screwup; } while (0) setimes = targisdir = 0; mask = umask(0); @@ -746,7 +772,7 @@ cursize = need; } (void) snprintf(namebuf, need, "%s%s%s", targ, - *targ ? "/" : "", cp); + strcmp(targ, "/") ? "/" : "", cp); np = namebuf; } else np = targ; @@ -784,7 +810,7 @@ } omode = mode; mode |= S_IWRITE; - if ((ofd = open(np, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) { + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { bad: run_err("%s: %s", np, strerror(errno)); continue; } @@ -808,7 +834,8 @@ count += amt; do { j = read(remin, cp, amt); - if (j == -1 && (errno == EINTR || errno == EAGAIN)) { + if (j == -1 && (errno == EINTR || + errno == EAGAIN)) { continue; } else if (j <= 0) { run_err("%s", j ? strerror(errno) : @@ -839,20 +866,26 @@ 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)); } @@ -886,7 +919,7 @@ } int -response() +response(void) { char ch, *cp, resp, rbuf[2048]; @@ -919,11 +952,12 @@ } void -usage() +usage(void) { - (void) fprintf(stderr, "usage: scp " - "[-pqrvBC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2\n" - " or: scp [options] f1 ... fn directory\n"); + (void) fprintf(stderr, + "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" + " [-c cipher] [-i identity] [-o option]\n" + " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); exit(1); } @@ -932,22 +966,24 @@ { 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: "); + va_start(ap, fmt); (void) vfprintf(fp, fmt, ap); + va_end(ap); (void) fprintf(fp, "\n"); (void) fflush(fp); if (!iamremote) { + va_start(ap, fmt); vfprintf(stderr, fmt, ap); + va_end(ap); fprintf(stderr, "\n"); } - va_end(ap); } void @@ -974,7 +1010,7 @@ cp = cp0; do { - c = *cp; + c = (int)*cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit(c) && @@ -993,6 +1029,7 @@ int fd, blksize; { size_t size; +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE struct stat stb; if (fstat(fd, &stb) < 0) { @@ -1004,12 +1041,16 @@ else size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % stb.st_blksize; +#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ + size = blksize; +#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ if (bp->cnt >= size) return (bp); if (bp->buf == NULL) bp->buf = xmalloc(size); else bp->buf = xrealloc(bp->buf, size); + memset(bp->buf, 0, size); bp->cnt = size; return (bp); } @@ -1019,32 +1060,25 @@ int signo; { if (!iamremote) - fprintf(stderr, "lost connection\n"); - exit(1); -} - - -void -alarmtimer(int wait) -{ - struct itimerval itv; - - itv.it_value.tv_sec = wait; - itv.it_value.tv_usec = 0; - itv.it_interval = itv.it_value; - setitimer(ITIMER_REAL, &itv, NULL); + write(STDERR_FILENO, "lost connection\n", 16); + if (signo) + _exit(1); + else + exit(1); } -void +static void updateprogressmeter(int ignore) { int save_errno = errno; progressmeter(0); + signal(SIGALRM, updateprogressmeter); + alarm(PROGRESSTIME); errno = save_errno; } -int +static int foregroundproc(void) { static pid_t pgrp = -1; @@ -1053,8 +1087,13 @@ if (pgrp == -1) pgrp = getpgrp(); +#ifdef HAVE_TCGETPGRP + return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 && + ctty_pgrp == pgrp); +#else return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 && ctty_pgrp == pgrp)); +#endif } void @@ -1067,7 +1106,7 @@ off_t cursize, abbrevsize; double elapsed; int ratio, barlength, i, remaining; - char buf[256]; + char buf[512]; if (flag == -1) { (void) gettimeofday(&start, (struct timezone *) 0); @@ -1093,8 +1132,13 @@ i = barlength * ratio / 100; snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "|%.*s%*s|", i, - "*****************************************************************************" - "*****************************************************************************", + "*******************************************************" + "*******************************************************" + "*******************************************************" + "*******************************************************" + "*******************************************************" + "*******************************************************" + "*******************************************************", barlength - i, ""); } i = 0; @@ -1103,8 +1147,8 @@ i++; abbrevsize >>= 10; } - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5llu %c%c ", - (unsigned long long) abbrevsize, prefixes[i], + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5lu %c%c ", + (unsigned long) abbrevsize, prefixes[i], prefixes[i] == ' ' ? ' ' : 'B'); timersub(&now, &lastupdate, &wait); @@ -1149,10 +1193,10 @@ atomicio(write, fileno(stdout), buf, strlen(buf)); if (flag == -1) { - signal(SIGALRM, updateprogressmeter); - alarmtimer(1); + mysignal(SIGALRM, updateprogressmeter); + alarm(PROGRESSTIME); } else if (flag == 1) { - alarmtimer(0); + alarm(0); atomicio(write, fileno(stdout), "\n", 1); statbytes = 0; } @@ -1167,26 +1211,4 @@ return (winsize.ws_col ? winsize.ws_col : 80); else return (80); -} - -void -addargs(char *fmt, ...) -{ - va_list ap; - char buf[1024]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - if (args.list == NULL) { - args.nalloc = 32; - args.num = 0; - args.list = xmalloc(args.nalloc * sizeof(char *)); - } else if (args.num+2 >= args.nalloc) { - args.nalloc *= 2; - args.list = xrealloc(args.list, args.nalloc * sizeof(char *)); - } - args.list[args.num++] = xstrdup(buf); - args.list[args.num] = NULL; } Index: src/crypto/openssh/servconf.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/servconf.c,v retrieving revision 1.3.2.13 diff -u -u -r1.3.2.13 servconf.c --- src/crypto/openssh/servconf.c 25 Apr 2002 16:53:25 -0000 1.3.2.13 +++ src/crypto/openssh/servconf.c 1 Jul 2002 14:58:25 -0000 @@ -10,12 +10,21 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.78 2001/04/15 21:28:35 stevesk Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/servconf.c,v 1.3.2.13 2002/04/25 16:53:25 des Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.112 2002/06/23 09:46:51 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/servconf.c,v 1.37 2002/06/29 11:48:58 des Exp $"); -#ifdef KRB4 +#if defined(KRB4) #include #endif +#if defined(KRB5) +#ifdef HEIMDAL +#include +#else +/* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V + * keytab */ +#define KEYFILE "/etc/krb5.keytab" +#endif +#endif #ifdef AFS #include #endif @@ -32,11 +41,13 @@ #include "kex.h" #include "mac.h" -void add_listen_addr(ServerOptions *options, char *addr, u_short port); -void add_one_listen_addr(ServerOptions *options, char *addr, u_short port); +static void add_listen_addr(ServerOptions *, char *, u_short); +static void add_one_listen_addr(ServerOptions *, char *, u_short); /* AF_UNSPEC or AF_INET or AF_INET6 */ extern int IPv4or6; +/* Use of privilege separation or not */ +extern int use_privsep; /* Initializes the server options to their default values. */ @@ -44,6 +55,11 @@ initialize_server_options(ServerOptions *options) { memset(options, 0, sizeof(*options)); + + /* Portable-specific options */ + options->pam_authentication_via_kbd_int = -1; + + /* Standard Options */ options->num_ports = 0; options->ports_from_cmdline = 0; options->listen_addrs = NULL; @@ -57,14 +73,14 @@ options->ignore_user_known_hosts = -1; options->print_motd = -1; options->print_lastlog = -1; - options->check_mail = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; + options->x11_use_localhost = -1; options->xauth_location = NULL; options->strict_modes = -1; options->keepalives = -1; - options->log_facility = (SyslogFacility) - 1; - options->log_level = (LogLevel) - 1; + options->log_facility = SYSLOG_FACILITY_NOT_SET; + options->log_level = SYSLOG_LEVEL_NOT_SET; options->rhosts_authentication = -1; options->rhosts_rsa_authentication = -1; options->hostbased_authentication = -1; @@ -73,23 +89,21 @@ options->pubkey_authentication = -1; #if defined(KRB4) || defined(KRB5) options->kerberos_authentication = -1; + options->kerberos_or_local_passwd = -1; + options->kerberos_ticket_cleanup = -1; +#endif +#if defined(AFS) || defined(KRB5) + options->kerberos_tgt_passing = -1; #endif -#ifdef KRB4 - options->krb4_or_local_passwd = -1; - options->krb4_ticket_cleanup = -1; -#endif -#ifdef KRB5 - options->krb5_tgt_passing = -1; -#endif /* KRB5 */ #ifdef AFS - options->krb4_tgt_passing = -1; options->afs_token_passing = -1; #endif options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->challenge_reponse_authentication = -1; + options->challenge_response_authentication = -1; options->permit_empty_passwd = -1; options->use_login = -1; + options->compression = -1; options->allow_tcp_forwarding = -1; options->num_allow_users = 0; options->num_deny_users = 0; @@ -99,29 +113,40 @@ options->macs = NULL; options->protocol = SSH_PROTO_UNKNOWN; options->gateway_ports = -1; - options->connections_per_period = 0; - options->connections_period = 0; options->num_subsystems = 0; options->max_startups_begin = -1; options->max_startups_rate = -1; options->max_startups = -1; options->banner = NULL; - options->reverse_mapping_check = -1; + options->verify_reverse_mapping = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; + options->authorized_keys_file = NULL; + options->authorized_keys_file2 = NULL; + + /* Needs to be accessable in many places */ + use_privsep = -1; } void fill_default_server_options(ServerOptions *options) { + /* Portable-specific options */ + if (options->pam_authentication_via_kbd_int == -1) + options->pam_authentication_via_kbd_int = 0; + + /* Standard Options */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_1|SSH_PROTO_2; if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ if (options->protocol & SSH_PROTO_1) - options->host_key_files[options->num_host_key_files++] = _PATH_HOST_KEY_FILE; - if (options->protocol & SSH_PROTO_2) - options->host_key_files[options->num_host_key_files++] = _PATH_HOST_DSA_KEY_FILE; + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_KEY_FILE; + if (options->protocol & SSH_PROTO_2) { + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_DSA_KEY_FILE; + } } if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; @@ -141,8 +166,6 @@ options->ignore_rhosts = 1; if (options->ignore_user_known_hosts == -1) options->ignore_user_known_hosts = 0; - if (options->check_mail == -1) - options->check_mail = 1; if (options->print_motd == -1) options->print_motd = 1; if (options->print_lastlog == -1) @@ -151,17 +174,17 @@ options->x11_forwarding = 1; if (options->x11_display_offset == -1) options->x11_display_offset = 10; -#ifdef XAUTH_PATH + if (options->x11_use_localhost == -1) + options->x11_use_localhost = 1; if (options->xauth_location == NULL) - options->xauth_location = XAUTH_PATH; -#endif /* XAUTH_PATH */ + options->xauth_location = _PATH_XAUTH; if (options->strict_modes == -1) options->strict_modes = 1; if (options->keepalives == -1) options->keepalives = 1; - if (options->log_facility == (SyslogFacility) (-1)) + if (options->log_facility == SYSLOG_FACILITY_NOT_SET) options->log_facility = SYSLOG_FACILITY_AUTH; - if (options->log_level == (LogLevel) (-1)) + if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->rhosts_authentication == -1) options->rhosts_authentication = 0; @@ -176,42 +199,45 @@ if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; #if defined(KRB4) && defined(KRB5) - if (options->kerberos_authentication == -1) - options->kerberos_authentication = - (access(KEYFILE, R_OK) == 0) || (access(krb5_defkeyname, R_OK) == 0); + if (options->kerberos_authentication == -1) + options->kerberos_authentication = + (access(KEYFILE, R_OK) == 0 || + access(krb5_defkeyname, R_OK) == 0); #elif defined(KRB4) - if (options->kerberos_authentication == -1) - options->kerberos_authentication = (access(KEYFILE, R_OK) == 0); + if (options->kerberos_authentication == -1) + options->kerberos_authentication = + (access(KEYFILE, R_OK) == 0); #elif defined(KRB5) if (options->kerberos_authentication == -1) - options->kerberos_authentication = (access(krb5_defkeyname, R_OK) == 0); + options->kerberos_authentication = + (access(krb5_defkeyname, R_OK) == 0); +#endif +#if defined(KRB4) || defined(KRB5) + if (options->kerberos_or_local_passwd == -1) + options->kerberos_or_local_passwd = 1; + if (options->kerberos_ticket_cleanup == -1) + options->kerberos_ticket_cleanup = 1; +#endif +#if defined(AFS) || defined(KRB5) + if (options->kerberos_tgt_passing == -1) + options->kerberos_tgt_passing = 0; #endif -#ifdef KRB4 - if (options->krb4_or_local_passwd == -1) - options->krb4_or_local_passwd = 1; - if (options->krb4_ticket_cleanup == -1) - options->krb4_ticket_cleanup = 1; -#endif /* KRB4 */ -#ifdef KRB5 - if (options->krb5_tgt_passing == -1) - options->krb5_tgt_passing = 1; -#endif /* KRB5 */ #ifdef AFS - if (options->krb4_tgt_passing == -1) - options->krb4_tgt_passing = 0; if (options->afs_token_passing == -1) - options->afs_token_passing = k_hasafs(); -#endif /* AFS */ + options->afs_token_passing = 0; +#endif if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 0; - if (options->challenge_reponse_authentication == -1) - options->challenge_reponse_authentication = 1; + if (options->challenge_response_authentication == -1) + options->challenge_response_authentication = 1; if (options->permit_empty_passwd == -1) options->permit_empty_passwd = 0; if (options->use_login == -1) options->use_login = 0; + if (options->compression == -1) + options->compression = 1; if (options->allow_tcp_forwarding == -1) options->allow_tcp_forwarding = 1; if (options->gateway_ports == -1) @@ -222,44 +248,70 @@ options->max_startups_rate = 100; /* 100% */ if (options->max_startups_begin == -1) options->max_startups_begin = options->max_startups; - if (options->reverse_mapping_check == -1) - options->reverse_mapping_check = 0; + if (options->verify_reverse_mapping == -1) + options->verify_reverse_mapping = 0; if (options->client_alive_interval == -1) - options->client_alive_interval = 0; + options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; + if (options->authorized_keys_file2 == NULL) { + /* authorized_keys_file2 falls back to authorized_keys_file */ + if (options->authorized_keys_file != NULL) + options->authorized_keys_file2 = options->authorized_keys_file; + else + options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; + } + if (options->authorized_keys_file == NULL) + options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; + + /* Turn privilege separation off by default */ + if (use_privsep == -1) + use_privsep = 0; + +#if !defined(HAVE_MMAP_ANON_SHARED) + if (use_privsep && options->compression == 1) { + error("This platform does not support both privilege " + "separation and compression"); + error("Compression disabled"); + options->compression = 0; + } +#endif + } /* Keyword tokens. */ typedef enum { sBadOption, /* == unknown option */ + /* Portable-specific options */ + sPAMAuthenticationViaKbdInt, + /* Standard Options */ sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, #if defined(KRB4) || defined(KRB5) - sKerberosAuthentication, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, #endif -#ifdef KRB4 - sKrb4OrLocalPasswd, sKrb4TicketCleanup, +#if defined(AFS) || defined(KRB5) + sKerberosTgtPassing, #endif -#ifdef KRB5 - sKrb5TgtPassing, -#endif /* KRB5 */ #ifdef AFS - sKrb4TgtPassing, sAFSTokenPassing, + sAFSTokenPassing, #endif sChallengeResponseAuthentication, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, - sStrictModes, sEmptyPasswd, sKeepAlives, sCheckMail, - sUseLogin, sAllowTcpForwarding, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, + sStrictModes, sEmptyPasswd, sKeepAlives, + sUseLogin, sAllowTcpForwarding, sCompression, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, - sBanner, sReverseMappingCheck, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sVersionAddendum, sConnectionsPerPeriod + sBanner, sVerifyReverseMapping, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sUsePrivilegeSeparation, + sVersionAddendum, + sDeprecated } ServerOpCodes; /* Textual representation of the tokens. */ @@ -267,6 +319,11 @@ const char *name; ServerOpCodes opcode; } keywords[] = { + /* Portable-specific options */ +#if 0 + { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt }, +#endif + /* Standard Options */ { "port", sPort }, { "hostkey", sHostKeyFile }, { "hostdsakey", sHostKeyFile }, /* alias */ @@ -281,28 +338,25 @@ { "rhostsrsaauthentication", sRhostsRSAAuthentication }, { "hostbasedauthentication", sHostbasedAuthentication }, { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, + { "rsaauthentication", sRSAAuthentication }, { "pubkeyauthentication", sPubkeyAuthentication }, { "dsaauthentication", sPubkeyAuthentication }, /* alias */ - { "rsaauthentication", sRSAAuthentication }, #if defined(KRB4) || defined(KRB5) { "kerberosauthentication", sKerberosAuthentication }, + { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, + { "kerberosticketcleanup", sKerberosTicketCleanup }, +#endif +#if defined(AFS) || defined(KRB5) + { "kerberostgtpassing", sKerberosTgtPassing }, #endif -#ifdef KRB4 - { "kerberos4orlocalpasswd", sKrb4OrLocalPasswd }, - { "kerberos4ticketcleanup", sKrb4TicketCleanup }, -#endif -#ifdef KRB5 - { "kerberos5tgtpassing", sKrb5TgtPassing }, -#endif /* KRB5 */ #ifdef AFS - { "kerberos4tgtpassing", sKrb4TgtPassing }, { "afstokenpassing", sAFSTokenPassing }, #endif { "passwordauthentication", sPasswordAuthentication }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, { "challengeresponseauthentication", sChallengeResponseAuthentication }, { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */ - { "checkmail", sCheckMail }, + { "checkmail", sDeprecated }, { "listenaddress", sListenAddress }, { "printmotd", sPrintMotd }, { "printlastlog", sPrintLastLog }, @@ -310,10 +364,12 @@ { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, { "x11forwarding", sX11Forwarding }, { "x11displayoffset", sX11DisplayOffset }, + { "x11uselocalhost", sX11UseLocalhost }, { "xauthlocation", sXAuthLocation }, { "strictmodes", sStrictModes }, { "permitemptypasswords", sEmptyPasswd }, { "uselogin", sUseLogin }, + { "compression", sCompression }, { "keepalive", sKeepAlives }, { "allowtcpforwarding", sAllowTcpForwarding }, { "allowusers", sAllowUsers }, @@ -324,15 +380,18 @@ { "macs", sMacs }, { "protocol", sProtocol }, { "gatewayports", sGatewayPorts }, - { "connectionsperperiod", sConnectionsPerPeriod }, { "subsystem", sSubsystem }, { "maxstartups", sMaxStartups }, - { "versionaddendum", sVersionAddendum }, { "banner", sBanner }, - { "reversemappingcheck", sReverseMappingCheck }, + { "verifyreversemapping", sVerifyReverseMapping }, + { "reversemappingcheck", sVerifyReverseMapping }, { "clientaliveinterval", sClientAliveInterval }, { "clientalivecountmax", sClientAliveCountMax }, - { NULL, 0 } + { "authorizedkeysfile", sAuthorizedKeysFile }, + { "authorizedkeysfile2", sAuthorizedKeysFile2 }, + { "useprivilegeseparation", sUsePrivilegeSeparation}, + { "versionaddendum", sVersionAddendum }, + { NULL, sBadOption } }; /* @@ -354,7 +413,7 @@ return sBadOption; } -void +static void add_listen_addr(ServerOptions *options, char *addr, u_short port) { int i; @@ -368,7 +427,7 @@ add_one_listen_addr(options, addr, port); } -void +static void add_one_listen_addr(ServerOptions *options, char *addr, u_short port) { struct addrinfo hints, *ai, *aitop; @@ -379,7 +438,7 @@ hints.ai_family = IPv4or6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; - snprintf(strport, sizeof strport, "%d", port); + snprintf(strport, sizeof strport, "%u", port); if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) fatal("bad addr or host: %s (%s)", addr ? addr : "", @@ -390,479 +449,520 @@ options->listen_addrs = aitop; } -/* Reads the server configuration file. */ - -void -read_server_config(ServerOptions *options, const char *filename) +int +process_server_config_line(ServerOptions *options, char *line, + const char *filename, int linenum) { - FILE *f; - char line[1024]; char *cp, **charptr, *arg, *p; - int linenum, *intptr, value; - int bad_options = 0; + int *intptr, value, i, n; ServerOpCodes opcode; - int i; - f = fopen(filename, "r"); - if (!f) { - perror(filename); - exit(1); - } - linenum = 0; - while (fgets(line, sizeof(line), f)) { - linenum++; - cp = line; + cp = line; + arg = strdelim(&cp); + /* Ignore leading whitespace */ + if (*arg == '\0') arg = strdelim(&cp); - /* Ignore leading whitespace */ - if (*arg == '\0') - arg = strdelim(&cp); - if (!arg || !*arg || *arg == '#') - continue; - intptr = NULL; - charptr = NULL; - opcode = parse_token(arg, filename, linenum); - switch (opcode) { - case sBadOption: - bad_options++; - continue; - case sPort: - /* ignore ports from configfile if cmdline specifies ports */ - if (options->ports_from_cmdline) - continue; - if (options->listen_addrs != NULL) - fatal("%s line %d: ports must be specified before " - "ListenAdress.\n", filename, linenum); - if (options->num_ports >= MAX_PORTS) - fatal("%s line %d: too many ports.", - filename, linenum); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing port number.", - filename, linenum); - options->ports[options->num_ports++] = a2port(arg); - if (options->ports[options->num_ports-1] == 0) - fatal("%s line %d: Badly formatted port number.", - filename, linenum); - break; + if (!arg || !*arg || *arg == '#') + return 0; + intptr = NULL; + charptr = NULL; + opcode = parse_token(arg, filename, linenum); + switch (opcode) { + /* Portable-specific options */ + case sPAMAuthenticationViaKbdInt: + intptr = &options->pam_authentication_via_kbd_int; + goto parse_flag; + + /* Standard Options */ + case sBadOption: + return -1; + case sPort: + /* ignore ports from configfile if cmdline specifies ports */ + if (options->ports_from_cmdline) + return 0; + if (options->listen_addrs != NULL) + fatal("%s line %d: ports must be specified before " + "ListenAddress.", filename, linenum); + if (options->num_ports >= MAX_PORTS) + fatal("%s line %d: too many ports.", + filename, linenum); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing port number.", + filename, linenum); + options->ports[options->num_ports++] = a2port(arg); + if (options->ports[options->num_ports-1] == 0) + fatal("%s line %d: Badly formatted port number.", + filename, linenum); + break; - case sServerKeyBits: - intptr = &options->server_key_bits; + case sServerKeyBits: + intptr = &options->server_key_bits; parse_int: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing integer value.", + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing integer value.", + filename, linenum); + value = atoi(arg); + if (*intptr == -1) + *intptr = value; + break; + + case sLoginGraceTime: + intptr = &options->login_grace_time; +parse_time: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing time value.", + filename, linenum); + if ((value = convtime(arg)) == -1) + fatal("%s line %d: invalid time value.", + filename, linenum); + if (*intptr == -1) + *intptr = value; + break; + + case sKeyRegenerationTime: + intptr = &options->key_regeneration_time; + goto parse_time; + + case sListenAddress: + arg = strdelim(&cp); + if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) + fatal("%s line %d: missing inet addr.", + filename, linenum); + if (*arg == '[') { + if ((p = strchr(arg, ']')) == NULL) + fatal("%s line %d: bad ipv6 inet addr usage.", filename, linenum); - value = atoi(arg); - if (value == 0) { - fprintf(stderr, "%s line %d: invalid integer value.\n", - filename, linenum); - exit(1); - } - if (*intptr == -1) - *intptr = value; + arg++; + memmove(p, p+1, strlen(p+1)+1); + } else if (((p = strchr(arg, ':')) == NULL) || + (strchr(p+1, ':') != NULL)) { + add_listen_addr(options, arg, 0); break; + } + if (*p == ':') { + u_short port; - case sLoginGraceTime: - intptr = &options->login_grace_time; - goto parse_int; - - case sKeyRegenerationTime: - intptr = &options->key_regeneration_time; - goto parse_int; - - case sListenAddress: - arg = strdelim(&cp); - if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) - fatal("%s line %d: missing inet addr.", + p++; + if (*p == '\0') + fatal("%s line %d: bad inet addr:port usage.", filename, linenum); - if (*arg == '[') { - if ((p = strchr(arg, ']')) == NULL) - fatal("%s line %d: bad ipv6 inet addr usage.", + else { + *(p-1) = '\0'; + if ((port = a2port(p)) == 0) + fatal("%s line %d: bad port number.", filename, linenum); - arg++; - memmove(p, p+1, strlen(p+1)+1); - } else if (((p = strchr(arg, ':')) == NULL) || - (strchr(p+1, ':') != NULL)) { - add_listen_addr(options, arg, 0); - break; + add_listen_addr(options, arg, port); } - if (*p == ':') { - u_short port; - - p++; - if (*p == '\0') - fatal("%s line %d: bad inet addr:port usage.", - filename, linenum); - else { - *(p-1) = '\0'; - if ((port = a2port(p)) == 0) - fatal("%s line %d: bad port number.", - filename, linenum); - add_listen_addr(options, arg, port); - } - } else if (*p == '\0') - add_listen_addr(options, arg, 0); - else - fatal("%s line %d: bad inet addr usage.", - filename, linenum); - break; - - case sHostKeyFile: - intptr = &options->num_host_key_files; - if (*intptr >= MAX_HOSTKEYS) - fatal("%s line %d: too many host keys specified (max %d).", - filename, linenum, MAX_HOSTKEYS); - charptr = &options->host_key_files[*intptr]; + } else if (*p == '\0') + add_listen_addr(options, arg, 0); + else + fatal("%s line %d: bad inet addr usage.", + filename, linenum); + break; + + case sHostKeyFile: + intptr = &options->num_host_key_files; + if (*intptr >= MAX_HOSTKEYS) + fatal("%s line %d: too many host keys specified (max %d).", + filename, linenum, MAX_HOSTKEYS); + charptr = &options->host_key_files[*intptr]; parse_filename: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing file name.", - filename, linenum); - if (*charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ - if (intptr != NULL) - *intptr = *intptr + 1; - } - break; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing file name.", + filename, linenum); + if (*charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ + if (intptr != NULL) + *intptr = *intptr + 1; + } + break; - case sPidFile: - charptr = &options->pid_file; - goto parse_filename; - - case sPermitRootLogin: - intptr = &options->permit_root_login; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/" - "without-password/forced-commands-only/no " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "without-password") == 0) - value = PERMIT_NO_PASSWD; - else if (strcmp(arg, "forced-commands-only") == 0) - value = PERMIT_FORCED_ONLY; - else if (strcmp(arg, "yes") == 0) - value = PERMIT_YES; - else if (strcmp(arg, "no") == 0) - value = PERMIT_NO; - else - fatal("%s line %d: Bad yes/" - "without-password/forced-commands-only/no " - "argument: %s", filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + case sPidFile: + charptr = &options->pid_file; + goto parse_filename; - case sIgnoreRhosts: - intptr = &options->ignore_rhosts; + case sPermitRootLogin: + intptr = &options->permit_root_login; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/" + "without-password/forced-commands-only/no " + "argument.", filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "without-password") == 0) + value = PERMIT_NO_PASSWD; + else if (strcmp(arg, "forced-commands-only") == 0) + value = PERMIT_FORCED_ONLY; + else if (strcmp(arg, "yes") == 0) + value = PERMIT_YES; + else if (strcmp(arg, "no") == 0) + value = PERMIT_NO; + else + fatal("%s line %d: Bad yes/" + "without-password/forced-commands-only/no " + "argument: %s", filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; + + case sIgnoreRhosts: + intptr = &options->ignore_rhosts; parse_flag: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no argument.", - filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no argument: %s", - filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/no argument.", + filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "yes") == 0) + value = 1; + else if (strcmp(arg, "no") == 0) + value = 0; + else + fatal("%s line %d: Bad yes/no argument: %s", + filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; + + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + goto parse_flag; + + case sRhostsAuthentication: + intptr = &options->rhosts_authentication; + goto parse_flag; + + case sRhostsRSAAuthentication: + intptr = &options->rhosts_rsa_authentication; + goto parse_flag; + + case sHostbasedAuthentication: + intptr = &options->hostbased_authentication; + goto parse_flag; + + case sHostbasedUsesNameFromPacketOnly: + intptr = &options->hostbased_uses_name_from_packet_only; + goto parse_flag; + + case sRSAAuthentication: + intptr = &options->rsa_authentication; + goto parse_flag; + + case sPubkeyAuthentication: + intptr = &options->pubkey_authentication; + goto parse_flag; +#if defined(KRB4) || defined(KRB5) + case sKerberosAuthentication: + intptr = &options->kerberos_authentication; + goto parse_flag; + + case sKerberosOrLocalPasswd: + intptr = &options->kerberos_or_local_passwd; + goto parse_flag; + + case sKerberosTicketCleanup: + intptr = &options->kerberos_ticket_cleanup; + goto parse_flag; +#endif +#if defined(AFS) || defined(KRB5) + 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 sIgnoreUserKnownHosts: - intptr = &options->ignore_user_known_hosts; - goto parse_flag; - - case sRhostsAuthentication: - intptr = &options->rhosts_authentication; - goto parse_flag; - - case sRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; - - case sHostbasedAuthentication: - intptr = &options->hostbased_authentication; - goto parse_flag; - - case sHostbasedUsesNameFromPacketOnly: - intptr = &options->hostbased_uses_name_from_packet_only; - goto parse_flag; - - case sRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; - - case sPubkeyAuthentication: - intptr = &options->pubkey_authentication; - goto parse_flag; + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; -#if defined(KRB4) || defined(KRB5) - case sKerberosAuthentication: - intptr = &options->kerberos_authentication; - goto parse_flag; -#endif - -#ifdef KRB4 - case sKrb4OrLocalPasswd: - intptr = &options->krb4_or_local_passwd; - goto parse_flag; - - case sKrb4TicketCleanup: - intptr = &options->krb4_ticket_cleanup; - goto parse_flag; -#endif - -#ifdef KRB5 - case sKrb5TgtPassing: - intptr = &options->krb5_tgt_passing; - goto parse_flag; -#endif /* KRB5 */ + case sKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; -#ifdef AFS - case sKrb4TgtPassing: - intptr = &options->krb4_tgt_passing; - goto parse_flag; - - case sAFSTokenPassing: - intptr = &options->afs_token_passing; - goto parse_flag; -#endif - - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; - - case sKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; - - case sCheckMail: - intptr = &options->check_mail; - goto parse_flag; - - case sChallengeResponseAuthentication: - intptr = &options->challenge_reponse_authentication; - goto parse_flag; - - case sPrintMotd: - intptr = &options->print_motd; - goto parse_flag; - - case sPrintLastLog: - intptr = &options->print_lastlog; - goto parse_flag; - - case sX11Forwarding: - intptr = &options->x11_forwarding; - goto parse_flag; - - case sX11DisplayOffset: - intptr = &options->x11_display_offset; - goto parse_int; - - case sXAuthLocation: - charptr = &options->xauth_location; - goto parse_filename; - - 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 sUseLogin: - intptr = &options->use_login; - goto parse_flag; - - case sGatewayPorts: - intptr = &options->gateway_ports; - goto parse_flag; - - case sReverseMappingCheck: - intptr = &options->reverse_mapping_check; - goto parse_flag; - - case sLogFacility: - intptr = (int *) &options->log_facility; - arg = strdelim(&cp); - value = log_facility_number(arg); - if (value == (SyslogFacility) - 1) - fatal("%.200s line %d: unsupported log facility '%s'", - filename, linenum, arg ? arg : ""); - if (*intptr == -1) - *intptr = (SyslogFacility) value; - break; + case sChallengeResponseAuthentication: + intptr = &options->challenge_response_authentication; + goto parse_flag; - case sLogLevel: - intptr = (int *) &options->log_level; - arg = strdelim(&cp); - value = log_level_number(arg); - if (value == (LogLevel) - 1) - fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : ""); - if (*intptr == -1) - *intptr = (LogLevel) value; - break; + case sPrintMotd: + intptr = &options->print_motd; + goto parse_flag; - case sAllowTcpForwarding: - intptr = &options->allow_tcp_forwarding; - goto parse_flag; - - case sAllowUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_users >= MAX_ALLOW_USERS) - fatal("%.200s line %d: too many allow users.", - filename, linenum); - options->allow_users[options->num_allow_users++] = xstrdup(arg); - } - break; + case sPrintLastLog: + intptr = &options->print_lastlog; + goto parse_flag; - case sDenyUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_deny_users >= MAX_DENY_USERS) - fatal(".200%s line %d: too many deny users.", - filename, linenum); - options->deny_users[options->num_deny_users++] = xstrdup(arg); - } - break; + case sX11Forwarding: + intptr = &options->x11_forwarding; + goto parse_flag; - case sAllowGroups: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_groups >= MAX_ALLOW_GROUPS) - fatal("%.200s line %d: too many allow groups.", - filename, linenum); - options->allow_groups[options->num_allow_groups++] = xstrdup(arg); - } - break; + case sX11DisplayOffset: + intptr = &options->x11_display_offset; + goto parse_int; - case sDenyGroups: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_deny_groups >= MAX_DENY_GROUPS) - fatal("%.200s line %d: too many deny groups.", - filename, linenum); - options->deny_groups[options->num_deny_groups++] = xstrdup(arg); - } - break; + case sX11UseLocalhost: + intptr = &options->x11_use_localhost; + goto parse_flag; - case sCiphers: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) - fatal("%s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : ""); - if (options->ciphers == NULL) - options->ciphers = xstrdup(arg); - break; + case sXAuthLocation: + charptr = &options->xauth_location; + goto parse_filename; - case sMacs: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) - fatal("%s line %d: Bad SSH2 mac spec '%s'.", - filename, linenum, arg ? arg : ""); - if (options->macs == NULL) - options->macs = xstrdup(arg); - break; + case sStrictModes: + intptr = &options->strict_modes; + goto parse_flag; - case sProtocol: - intptr = &options->protocol; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - value = proto_spec(arg); - if (value == SSH_PROTO_UNKNOWN) - fatal("%s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : ""); - if (*intptr == SSH_PROTO_UNKNOWN) - *intptr = value; - break; + case sKeepAlives: + intptr = &options->keepalives; + goto parse_flag; - case sConnectionsPerPeriod: - (void)strdelim(&cp); - error("ConnectionsPerPeriod has been deprecated!"); - break; + case sEmptyPasswd: + intptr = &options->permit_empty_passwd; + goto parse_flag; - case sSubsystem: - if(options->num_subsystems >= MAX_SUBSYSTEMS) { - fatal("%s line %d: too many subsystems defined.", - filename, linenum); - } - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - for (i = 0; i < options->num_subsystems; i++) - if(strcmp(arg, options->subsystem_name[i]) == 0) - fatal("%s line %d: Subsystem '%s' already defined.", - filename, linenum, arg); - options->subsystem_name[options->num_subsystems] = xstrdup(arg); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem command.", - filename, linenum); - options->subsystem_command[options->num_subsystems] = xstrdup(arg); - options->num_subsystems++; - break; + case sUseLogin: + intptr = &options->use_login; + goto parse_flag; - case sMaxStartups: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing MaxStartups spec.", - filename, linenum); - if (sscanf(arg, "%d:%d:%d", - &options->max_startups_begin, - &options->max_startups_rate, - &options->max_startups) == 3) { - if (options->max_startups_begin > - options->max_startups || - options->max_startups_rate > 100 || - options->max_startups_rate < 1) - fatal("%s line %d: Illegal MaxStartups spec.", - filename, linenum); - break; - } - intptr = &options->max_startups; - goto parse_int; + case sCompression: + intptr = &options->compression; + goto parse_flag; - case sVersionAddendum: - ssh_version_set_addendum(strtok(cp, "\n")); - do - arg = strdelim(&cp); - while (arg != NULL && *arg != '\0'); - break; + case sGatewayPorts: + intptr = &options->gateway_ports; + goto parse_flag; + + case sVerifyReverseMapping: + intptr = &options->verify_reverse_mapping; + goto parse_flag; + + case sLogFacility: + intptr = (int *) &options->log_facility; + arg = strdelim(&cp); + value = log_facility_number(arg); + if (value == SYSLOG_FACILITY_NOT_SET) + fatal("%.200s line %d: unsupported log facility '%s'", + filename, linenum, arg ? arg : ""); + if (*intptr == -1) + *intptr = (SyslogFacility) value; + break; + + case sLogLevel: + intptr = (int *) &options->log_level; + arg = strdelim(&cp); + value = log_level_number(arg); + if (value == SYSLOG_LEVEL_NOT_SET) + fatal("%.200s line %d: unsupported log level '%s'", + filename, linenum, arg ? arg : ""); + if (*intptr == -1) + *intptr = (LogLevel) value; + break; + + case sAllowTcpForwarding: + intptr = &options->allow_tcp_forwarding; + goto parse_flag; + + case sUsePrivilegeSeparation: + intptr = &use_privsep; + goto parse_flag; + + case sAllowUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_users >= MAX_ALLOW_USERS) + fatal("%s line %d: too many allow users.", + filename, linenum); + options->allow_users[options->num_allow_users++] = + xstrdup(arg); + } + break; + + case sDenyUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_deny_users >= MAX_DENY_USERS) + fatal( "%s line %d: too many deny users.", + filename, linenum); + options->deny_users[options->num_deny_users++] = + xstrdup(arg); + } + break; + + case sAllowGroups: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_groups >= MAX_ALLOW_GROUPS) + fatal("%s line %d: too many allow groups.", + filename, linenum); + options->allow_groups[options->num_allow_groups++] = + xstrdup(arg); + } + break; + + case sDenyGroups: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_deny_groups >= MAX_DENY_GROUPS) + fatal("%s line %d: too many deny groups.", + filename, linenum); + options->deny_groups[options->num_deny_groups++] = xstrdup(arg); + } + break; + + case sCiphers: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (!ciphers_valid(arg)) + fatal("%s line %d: Bad SSH2 cipher spec '%s'.", + filename, linenum, arg ? arg : ""); + if (options->ciphers == NULL) + options->ciphers = xstrdup(arg); + break; + + case sMacs: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (!mac_valid(arg)) + fatal("%s line %d: Bad SSH2 mac spec '%s'.", + filename, linenum, arg ? arg : ""); + if (options->macs == NULL) + options->macs = xstrdup(arg); + break; - case sBanner: - charptr = &options->banner; - goto parse_filename; - case sClientAliveInterval: - intptr = &options->client_alive_interval; - goto parse_int; - case sClientAliveCountMax: - intptr = &options->client_alive_count_max; - goto parse_int; - default: - fatal("%.200s line %d: Missing handler for opcode %s (%d)", - filename, linenum, arg, opcode); + case sProtocol: + intptr = &options->protocol; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + value = proto_spec(arg); + if (value == SSH_PROTO_UNKNOWN) + fatal("%s line %d: Bad protocol spec '%s'.", + filename, linenum, arg ? arg : ""); + if (*intptr == SSH_PROTO_UNKNOWN) + *intptr = value; + break; + + case sSubsystem: + if (options->num_subsystems >= MAX_SUBSYSTEMS) { + fatal("%s line %d: too many subsystems defined.", + filename, linenum); } - if ((arg = strdelim(&cp)) != NULL && *arg != '\0') - fatal("%s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing subsystem name.", + filename, linenum); + for (i = 0; i < options->num_subsystems; i++) + if (strcmp(arg, options->subsystem_name[i]) == 0) + fatal("%s line %d: Subsystem '%s' already defined.", + filename, linenum, arg); + options->subsystem_name[options->num_subsystems] = xstrdup(arg); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing subsystem command.", + filename, linenum); + options->subsystem_command[options->num_subsystems] = xstrdup(arg); + options->num_subsystems++; + break; + + case sMaxStartups: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing MaxStartups spec.", + filename, linenum); + if ((n = sscanf(arg, "%d:%d:%d", + &options->max_startups_begin, + &options->max_startups_rate, + &options->max_startups)) == 3) { + if (options->max_startups_begin > + options->max_startups || + options->max_startups_rate > 100 || + options->max_startups_rate < 1) + fatal("%s line %d: Illegal MaxStartups spec.", + filename, linenum); + } else if (n != 1) + fatal("%s line %d: Illegal MaxStartups spec.", + filename, linenum); + else + options->max_startups = options->max_startups_begin; + break; + + case sBanner: + charptr = &options->banner; + goto parse_filename; + /* + * These options can contain %X options expanded at + * connect time, so that you can specify paths like: + * + * AuthorizedKeysFile /etc/ssh_keys/%u + */ + case sAuthorizedKeysFile: + case sAuthorizedKeysFile2: + charptr = (opcode == sAuthorizedKeysFile ) ? + &options->authorized_keys_file : + &options->authorized_keys_file2; + goto parse_filename; + + case sClientAliveInterval: + intptr = &options->client_alive_interval; + goto parse_time; + + case sClientAliveCountMax: + intptr = &options->client_alive_count_max; + goto parse_int; + + case sVersionAddendum: + ssh_version_set_addendum(strtok(cp, "\n")); + do { + arg = strdelim(&cp); + } while (arg != NULL && *arg != '\0'); + break; + + case sDeprecated: + log("%s line %d: Deprecated option %s", + filename, linenum, arg); + while (arg) + arg = strdelim(&cp); + break; + + default: + fatal("%s line %d: Missing handler for opcode %s (%d)", + filename, linenum, arg, opcode); + } + if ((arg = strdelim(&cp)) != NULL && *arg != '\0') + fatal("%s line %d: garbage at end of line; \"%.200s\".", + filename, linenum, arg); + return 0; +} + +/* Reads the server configuration file. */ + +void +read_server_config(ServerOptions *options, const char *filename) +{ + int linenum, bad_options = 0; + char line[1024]; + FILE *f; + + f = fopen(filename, "r"); + if (!f) { + perror(filename); + exit(1); + } + linenum = 0; + while (fgets(line, sizeof(line), f)) { + /* Update line number counter. */ + linenum++; + if (process_server_config_line(options, line, filename, linenum) != 0) + bad_options++; } fclose(f); if (bad_options > 0) - fatal("%.200s: terminating, %d bad configuration options", + fatal("%s: terminating, %d bad configuration options", filename, bad_options); } Index: src/crypto/openssh/servconf.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/servconf.h,v retrieving revision 1.3.2.5 diff -u -u -r1.3.2.5 servconf.h --- src/crypto/openssh/servconf.h 28 Sep 2001 01:33:34 -0000 1.3.2.5 +++ src/crypto/openssh/servconf.h 30 Jun 2002 11:38:00 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: servconf.h,v 1.58 2002/06/20 23:05:55 markus Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,9 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: servconf.h,v 1.41 2001/04/13 22:46:53 beck Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/servconf.h,v 1.3.2.5 2001/09/28 01:33:34 green Exp $"); */ - #ifndef SERVCONF_H #define SERVCONF_H @@ -53,10 +52,10 @@ * for RhostsRsaAuth */ int print_motd; /* If true, print /etc/motd. */ int print_lastlog; /* If true, print lastlog */ - int check_mail; /* If true, check for new mail. */ int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ int x11_display_offset; /* What DISPLAY number to start * searching at */ + int x11_use_localhost; /* If true, use localhost for fake X11 server. */ char *xauth_location; /* Location of xauth program */ int strict_modes; /* If true, require string home dir modes. */ int keepalives; /* If true, set SO_KEEPALIVE. */ @@ -73,35 +72,33 @@ int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ int hostbased_uses_name_from_packet_only; /* experimental */ int rsa_authentication; /* If true, permit RSA authentication. */ -#if defined(KRB4) || defined(KRB5) - int kerberos_authentication; /* If true, permit Kerberos auth. */ -#endif /* KRB4 || KRB5 */ int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ -#ifdef KRB4 - int krb4_or_local_passwd; /* If true, permit kerberos v4 +#if defined(KRB4) || defined(KRB5) + int kerberos_authentication; /* If true, permit Kerberos + * authentication. */ + int kerberos_or_local_passwd; /* If true, permit kerberos * and any other password * authentication mechanism, * such as SecurID or * /etc/passwd */ - int krb4_ticket_cleanup; /* If true, destroy ticket + int kerberos_ticket_cleanup; /* If true, destroy ticket * file on logout. */ #endif -#ifdef KRB5 - int krb5_tgt_passing; - -#endif /* KRB5 */ -#ifdef AFS - int krb4_tgt_passing; /* If true, permit Kerberos v4 tgt +#if defined(AFS) || defined(KRB5) + 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 kbd_interactive_authentication; /* If true, permit */ - int challenge_reponse_authentication; + int challenge_response_authentication; int permit_empty_passwd; /* If false, do not permit empty * passwords. */ int use_login; /* If true, login(1) is used */ + int compression; /* If true, compression is allowed */ int allow_tcp_forwarding; u_int num_allow_users; char *allow_users[MAX_ALLOW_USERS]; @@ -111,12 +108,6 @@ char *allow_groups[MAX_ALLOW_GROUPS]; u_int num_deny_groups; char *deny_groups[MAX_DENY_GROUPS]; - unsigned int connections_per_period; /* - * If not 0, number of sshd - * connections accepted per - * connections_period. - */ - unsigned int connections_period; u_int num_subsystems; char *subsystem_name[MAX_SUBSYSTEMS]; @@ -126,31 +117,26 @@ int max_startups_rate; int max_startups; char *banner; /* SSH-2 banner message */ - int reverse_mapping_check; /* cross-check ip and dns */ + int verify_reverse_mapping; /* cross-check ip and dns */ int client_alive_interval; /* - * poke the client this often to - * see if it's still there + * poke the client this often to + * see if it's still there */ int client_alive_count_max; /* - *If the client is unresponsive - * for this many intervals, above - * diconnect the session + * If the client is unresponsive + * for this many intervals above, + * disconnect the session */ + char *authorized_keys_file; /* File containing public keys */ + char *authorized_keys_file2; + int pam_authentication_via_kbd_int; } 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); +void initialize_server_options(ServerOptions *); +void read_server_config(ServerOptions *, const char *); +void fill_default_server_options(ServerOptions *); +int process_server_config_line(ServerOptions *, char *, const char *, int); -/* Sets values for those values that have not yet been set. */ -void fill_default_server_options(ServerOptions * options); #endif /* SERVCONF_H */ Index: src/crypto/openssh/serverloop.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/serverloop.c,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 serverloop.c --- src/crypto/openssh/serverloop.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/serverloop.c 30 Jun 2002 11:38:00 -0000 @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 support by Markus Friedl. - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,8 +35,8 @@ */ #include "includes.h" -RCSID("$FreeBSD: src/crypto/openssh/serverloop.c,v 1.1.1.1.2.5 2001/09/28 01:33:34 green Exp $"); -RCSID("$OpenBSD: serverloop.c,v 1.61 2001/04/13 22:46:54 beck Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.103 2002/06/24 14:33:27 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/serverloop.c,v 1.7 2002/06/29 11:48:58 des Exp $"); #include "xmalloc.h" #include "packet.h" @@ -60,6 +60,7 @@ /* XXX */ extern Kex *xxx_kex; +static Authctxt *xxx_authctxt; static Buffer stdin_buffer; /* Buffer for stdin data. */ static Buffer stdout_buffer; /* Buffer for stdout data. */ @@ -80,46 +81,71 @@ static int connection_out; /* Connection to client (output). */ static int connection_closed = 0; /* Connection to client closed. */ static u_int buffer_high; /* "Soft" max buffer size. */ +static int client_alive_timeouts = 0; /* * 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 pid_t child_pid; /* Pid of the child. */ -static volatile int child_terminated; /* The child has terminated. */ -static volatile int child_wait_status; /* Status from wait(). */ +static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ -void server_init_dispatch(void); +/* prototypes */ +static void server_init_dispatch(void); -int client_alive_timeouts = 0; - -void -sigchld_handler(int sig) +/* + * we write to this pipe if a SIGCHLD is caught in order to avoid + * the race between select() and child_terminated + */ +static int notify_pipe[2]; +static void +notify_setup(void) +{ + if (pipe(notify_pipe) < 0) { + error("pipe(notify_pipe) failed %s", strerror(errno)); + } else if ((fcntl(notify_pipe[0], F_SETFD, 1) == -1) || + (fcntl(notify_pipe[1], F_SETFD, 1) == -1)) { + error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno)); + close(notify_pipe[0]); + close(notify_pipe[1]); + } else { + set_nonblock(notify_pipe[0]); + set_nonblock(notify_pipe[1]); + return; + } + notify_pipe[0] = -1; /* read end */ + notify_pipe[1] = -1; /* write end */ +} +static void +notify_parent(void) { - int save_errno = errno; - pid_t wait_pid; + if (notify_pipe[1] != -1) + write(notify_pipe[1], "", 1); +} +static void +notify_prepare(fd_set *readset) +{ + if (notify_pipe[0] != -1) + FD_SET(notify_pipe[0], readset); +} +static void +notify_done(fd_set *readset) +{ + char c; - 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); - errno = save_errno; + if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) + while (read(notify_pipe[0], &c, 1) != -1) + debug2("notify_done: reading"); } -void -sigchld_handler2(int sig) + +static void +sigchld_handler(int sig) { int save_errno = errno; debug("Received SIGCHLD."); child_terminated = 1; - signal(SIGCHLD, sigchld_handler2); + mysignal(SIGCHLD, sigchld_handler); + notify_parent(); errno = save_errno; } @@ -127,7 +153,7 @@ * Make packets from buffered stderr data, and buffer it for sending * to the client. */ -void +static void make_packets_from_stderr_data(void) { int len; @@ -156,7 +182,7 @@ * Make packets from buffered stdout data, and buffer it for sending to the * client. */ -void +static void make_packets_from_stdout_data(void) { int len; @@ -181,44 +207,69 @@ } } +static void +client_alive_check(void) +{ + static int had_channel = 0; + int id; + + id = channel_find_open(); + if (id == -1) { + if (!had_channel) + return; + packet_disconnect("No open channels after timeout!"); + } + had_channel = 1; + + /* timeout, check to see how many we have had */ + if (++client_alive_timeouts > options.client_alive_count_max) + packet_disconnect("Timeout, your session not responding."); + + /* + * send a bogus channel request with "wantreply", + * we should get back a failure + */ + channel_request_start(id, "keepalive@openssh.com", 1); + packet_send(); +} + /* * 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 +static void wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, - u_int max_time_milliseconds) + int *nallocp, u_int max_time_milliseconds) { struct timeval tv, *tvp; int ret; int client_alive_scheduled = 0; /* - * if using client_alive, set the max timeout accordingly, + * if using client_alive, set the max timeout accordingly, * and indicate that this particular timeout was for client * alive by setting the client_alive_scheduled flag. * * this could be randomized somewhat to make traffic - * analysis more difficult, but we're not doing it yet. + * analysis more difficult, but we're not doing it yet. */ - if (max_time_milliseconds == 0 && options.client_alive_interval) { - client_alive_scheduled = 1; + if (compat20 && + max_time_milliseconds == 0 && options.client_alive_interval) { + client_alive_scheduled = 1; max_time_milliseconds = options.client_alive_interval * 1000; - } else - client_alive_scheduled = 0; - - /* When select fails we restart from here. */ -retry_select: + } /* Allocate and update select() masks for channel descriptors. */ - channel_prepare_select(readsetp, writesetp, maxfdp, 0); + channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); if (compat20) { +#if 0 /* wrong: bad condition XXX */ if (channel_not_very_much_buffered_data()) - FD_SET(connection_in, *readsetp); +#endif + FD_SET(connection_in, *readsetp); } else { /* * Read packets from the client unless we have too much @@ -244,6 +295,7 @@ if (fdin != -1 && buffer_len(&stdin_buffer) > 0) FD_SET(fdin, *writesetp); } + notify_prepare(*readsetp); /* * If we have buffered packet data going to the client, mark that @@ -267,49 +319,26 @@ tv.tv_usec = 1000 * (max_time_milliseconds % 1000); tvp = &tv; } - if (tvp!=NULL) - debug3("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds); /* Wait for something to happen, or the timeout to expire. */ ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); if (ret == -1) { + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); if (errno != EINTR) error("select: %.100s", strerror(errno)); - else - goto retry_select; - } - if (ret == 0 && client_alive_scheduled) { - /* timeout, check to see how many we have had */ - client_alive_timeouts++; - - if (client_alive_timeouts > options.client_alive_count_max ) { - packet_disconnect( - "Timeout, your session not responding."); - } else { - /* - * send a bogus channel request with "wantreply" - * we should get back a failure - */ - int id; - - id = channel_find_open(); - if (id != -1) { - channel_request_start(id, - "keepalive@openssh.com", 1); - packet_send(); - } else - packet_disconnect( - "No open channels after timeout!"); - } - } + } else if (ret == 0 && client_alive_scheduled) + client_alive_check(); + + notify_done(*readsetp); } /* * Processes input from the client and the program. Input data is stored * in buffers and processed later. */ -void +static void process_input(fd_set * readset) { int len; @@ -365,31 +394,31 @@ /* * Sends data from internal buffers to client program stdin. */ -void +static void process_output(fd_set * writeset) { struct termios tio; + u_char *data; + u_int dlen; int len; /* Write buffered data to program stdin. */ if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { - len = write(fdin, buffer_ptr(&stdin_buffer), - buffer_len(&stdin_buffer)); + data = buffer_ptr(&stdin_buffer); + dlen = buffer_len(&stdin_buffer); + len = write(fdin, data, dlen); if (len < 0 && (errno == EINTR || errno == EAGAIN)) { /* do nothing */ } else if (len <= 0) { -#ifdef USE_PIPES - close(fdin); -#else if (fdin != fdout) close(fdin); else shutdown(fdin, SHUT_WR); /* We will no longer send. */ -#endif fdin = -1; } else { /* Successful write. */ - if (fdin_is_tty && tcgetattr(fdin, &tio) == 0 && + if (fdin_is_tty && dlen >= 1 && data[0] != '\r' && + tcgetattr(fdin, &tio) == 0 && !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { /* * Simulate echo to reduce the impact of @@ -413,7 +442,7 @@ * Wait until all buffered output has been sent to the client. * This is used when the program terminates. */ -void +static void drain_output(void) { /* Send any buffered stdout data to the client. */ @@ -438,7 +467,7 @@ packet_write_wait(); } -void +static void process_buffered_input_packets(void) { dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL); @@ -455,7 +484,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) { fd_set *readset = NULL, *writeset = NULL; - int max_fd; + int max_fd = 0, nalloc = 0; int wait_status; /* Status returned by wait(). */ pid_t wait_pid; /* pid returned by wait(). */ int waiting_termination = 0; /* Have displayed waiting close message. */ @@ -467,9 +496,8 @@ debug("Entering interactive session."); /* Initialize the SIGCHLD kludge. */ - child_pid = pid; child_terminated = 0; - signal(SIGCHLD, sigchld_handler); + mysignal(SIGCHLD, sigchld_handler); /* Initialize our global variables. */ fdin = fdin_arg; @@ -489,6 +517,8 @@ connection_in = packet_get_connection_in(); connection_out = packet_get_connection_out(); + notify_setup(); + previous_stdout_buffer_bytes = 0; /* Set approximate I/O buffer size. */ @@ -497,12 +527,14 @@ else buffer_high = 64 * 1024; +#if 0 /* Initialize max_fd to the maximum of the known file descriptors. */ - max_fd = MAX(fdin, fdout); + max_fd = MAX(connection_in, connection_out); + max_fd = MAX(max_fd, fdin); + max_fd = MAX(max_fd, fdout); if (fderr != -1) max_fd = MAX(max_fd, fderr); - max_fd = MAX(max_fd, connection_in); - max_fd = MAX(max_fd, connection_out); +#endif /* Initialize Initialize buffers. */ buffer_init(&stdin_buffer); @@ -531,14 +563,10 @@ * input data, cause a real eof by closing fdin. */ if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { -#ifdef USE_PIPES - close(fdin); -#else if (fdin != fdout) close(fdin); else shutdown(fdin, SHUT_WR); /* We will no longer send. */ -#endif fdin = -1; } /* Make packets from buffered stderr data to send to the client. */ @@ -588,9 +616,15 @@ xfree(cp); } } + max_fd = MAX(connection_in, connection_out); + max_fd = MAX(max_fd, fdin); + max_fd = MAX(max_fd, fdout); + max_fd = MAX(max_fd, fderr); + max_fd = MAX(max_fd, notify_pipe[0]); + /* Sleep in select() until we can do something. */ wait_until_can_do_something(&readset, &writeset, &max_fd, - max_time_milliseconds); + &nalloc, max_time_milliseconds); /* Process any channel events. */ channel_after_select(readset, writeset); @@ -612,7 +646,7 @@ 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); + stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes); /* Free and clear the buffers. */ buffer_free(&stdin_buffer); @@ -632,30 +666,17 @@ close(fdin); 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 == -1) { - /* - * 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); - } + channel_free_all(); /* We no longer want our SIGCHLD handler to be called. */ - signal(SIGCHLD, SIG_DFL); + mysignal(SIGCHLD, SIG_DFL); + + while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0) + if (errno != EINTR) + packet_disconnect("wait: %.100s", strerror(errno)); + if (wait_pid != pid) + error("Strange, wait returned pid %ld, expected %ld", + (long)wait_pid, (long)pid); /* Check if it exited normally. */ if (WIFEXITED(wait_status)) { @@ -674,8 +695,7 @@ * the exit status. */ do { - int plen; - type = packet_read(&plen); + type = packet_read(); } while (type != SSH_CMSG_EXIT_CONFIRMATION); @@ -692,21 +712,46 @@ /* NOTREACHED */ } +static void +collect_children(void) +{ + pid_t pid; + sigset_t oset, nset; + int status; + + /* block SIGCHLD while we check for dead children */ + sigemptyset(&nset); + sigaddset(&nset, SIGCHLD); + sigprocmask(SIG_BLOCK, &nset, &oset); + if (child_terminated) { + while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || + (pid < 0 && errno == EINTR)) + if (pid > 0) + session_close_by_pid(pid, status); + child_terminated = 0; + } + sigprocmask(SIG_SETMASK, &oset, NULL); +} + void -server_loop2(void) +server_loop2(Authctxt *authctxt) { fd_set *readset = NULL, *writeset = NULL; - int rekeying = 0, max_fd, status; - pid_t pid; + int rekeying = 0, max_fd, nalloc = 0; debug("Entering interactive session for SSH2."); - signal(SIGCHLD, sigchld_handler2); + mysignal(SIGCHLD, sigchld_handler); child_terminated = 0; connection_in = packet_get_connection_in(); connection_out = packet_get_connection_out(); + notify_setup(); + max_fd = MAX(connection_in, connection_out); + max_fd = MAX(max_fd, notify_pipe[0]); + + xxx_authctxt = authctxt; server_init_dispatch(); @@ -718,12 +763,9 @@ if (!rekeying && packet_not_very_much_data_to_write()) channel_output_poll(); wait_until_can_do_something(&readset, &writeset, &max_fd, - rekeying); - if (child_terminated) { - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) - session_close_by_pid(pid, status); - child_terminated = 0; - } + &nalloc, 0); + + collect_children(); if (!rekeying) channel_after_select(readset, writeset); process_input(readset); @@ -731,32 +773,35 @@ break; process_output(writeset); } + collect_children(); + if (readset) xfree(readset); if (writeset) xfree(writeset); - signal(SIGCHLD, SIG_DFL); - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) - session_close_by_pid(pid, status); - channel_stop_listening(); + /* free all channels, no more reads and writes */ + channel_free_all(); + + /* free remaining sessions, e.g. remove wtmp entries */ + session_destroy_all(NULL); } -void -server_input_channel_failure(int type, int plen, void *ctxt) +static void +server_input_channel_failure(int type, u_int32_t seq, void *ctxt) { debug("Got CHANNEL_FAILURE for keepalive"); - /* - * reset timeout, since we got a sane answer from the client. + /* + * reset timeout, since we got a sane answer from the client. * even if this was generated by something other than * the bogus CHANNEL_REQUEST we send for keepalives. */ - client_alive_timeouts = 0; + client_alive_timeouts = 0; } -void -server_input_stdin_data(int type, int plen, void *ctxt) +static void +server_input_stdin_data(int type, u_int32_t seq, void *ctxt) { char *data; u_int data_len; @@ -766,14 +811,14 @@ if (fdin == -1) return; data = packet_get_string(&data_len); - packet_integrity_check(plen, (4 + data_len), type); + packet_check_eom(); buffer_append(&stdin_buffer, data, data_len); memset(data, 0, data_len); xfree(data); } -void -server_input_eof(int type, int plen, void *ctxt) +static void +server_input_eof(int type, u_int32_t seq, void *ctxt) { /* * Eof from the client. The stdin descriptor to the @@ -781,12 +826,12 @@ * drained. */ debug("EOF received for stdin."); - packet_integrity_check(plen, 0, type); + packet_check_eom(); stdin_eof = 1; } -void -server_input_window_size(int type, int plen, void *ctxt) +static void +server_input_window_size(int type, u_int32_t seq, void *ctxt) { int row = packet_get_int(); int col = packet_get_int(); @@ -794,15 +839,16 @@ int ypixel = packet_get_int(); debug("Window change received."); - packet_integrity_check(plen, 4 * 4, type); + packet_check_eom(); if (fdin != -1) pty_change_window_size(fdin, row, col, xpixel, ypixel); } -Channel * +static Channel * server_request_direct_tcpip(char *ctype) { - int sock, newch; + Channel *c; + int sock; char *target, *originator; int target_port, originator_port; @@ -810,7 +856,7 @@ target_port = packet_get_int(); originator = packet_get_string(NULL); originator_port = packet_get_int(); - packet_done(); + packet_check_eom(); debug("server_request_direct_tcpip: originator %s port %d, target %s port %d", originator, originator_port, target, target_port); @@ -821,49 +867,44 @@ xfree(originator); if (sock < 0) return NULL; - newch = channel_new(ctype, SSH_CHANNEL_CONNECTING, + c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); - return (newch >= 0) ? channel_lookup(newch) : NULL; + return c; } -Channel * +static Channel * server_request_session(char *ctype) { - int newch; + Channel *c; debug("input_session_request"); - packet_done(); + packet_check_eom(); /* * A server session has no fd to read or write until a * CHANNEL_REQUEST for a shell is made, so we set the type to * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all * CHANNEL_REQUEST messages is registered. */ - newch = channel_new(ctype, SSH_CHANNEL_LARVAL, - -1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT, + c = channel_new(ctype, SSH_CHANNEL_LARVAL, + -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, xstrdup("server-session"), 1); - if (session_open(newch) == 1) { - channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST, - session_input_channel_req, (void *)0); - channel_register_cleanup(newch, session_close_by_channel); - return channel_lookup(newch); - } else { - debug("session open failed, free channel %d", newch); - channel_free(newch); + if (session_open(xxx_authctxt, c->self) != 1) { + debug("session open failed, free channel %d", c->self); + channel_free(c); + return NULL; } - return NULL; + channel_register_cleanup(c->self, session_close_by_channel); + return c; } -void -server_input_channel_open(int type, int plen, void *ctxt) +static void +server_input_channel_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; char *ctype; - u_int len; int rchan; - int rmaxpack; - int rwindow; + u_int rmaxpack, rwindow, len; ctype = packet_get_string(&len); rchan = packet_get_int(); @@ -883,27 +924,30 @@ c->remote_id = rchan; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; - - packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - packet_send(); + if (c->type != SSH_CHANNEL_CONNECTING) { + packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(c->remote_id); + packet_put_int(c->self); + packet_put_int(c->local_window); + packet_put_int(c->local_maxpacket); + packet_send(); + } } else { debug("server_input_channel_open: failure %s", ctype); packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); packet_put_int(rchan); packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); - packet_put_cstring("bla bla"); - packet_put_cstring(""); + if (!(datafellows & SSH_BUG_OPENFAILURE)) { + packet_put_cstring("open failed"); + packet_put_cstring(""); + } packet_send(); } xfree(ctype); } -void -server_input_global_request(int type, int plen, void *ctxt) +static void +server_input_global_request(int type, u_int32_t seq, void *ctxt) { char *rtype; int want_reply; @@ -935,11 +979,8 @@ packet_send_debug("Server has disabled port forwarding."); } else { /* Start listening on the port */ - success = channel_request_forwarding( - listen_address, listen_port, - /*unspec host_to_connect*/ "", - /*unspec port_to_connect*/ 0, - options.gateway_ports, /*remote*/ 1); + success = channel_setup_remote_fwd_listener( + listen_address, listen_port, options.gateway_ports); } xfree(listen_address); } @@ -951,8 +992,35 @@ } xfree(rtype); } +static void +server_input_channel_req(int type, u_int32_t seq, void *ctxt) +{ + Channel *c; + int id, reply, success = 0; + char *rtype; -void + id = packet_get_int(); + rtype = packet_get_string(NULL); + reply = packet_get_char(); + + debug("server_input_channel_req: channel %d request %s reply %d", + id, rtype, reply); + + if ((c = channel_lookup(id)) == NULL) + packet_disconnect("server_input_channel_req: " + "unknown channel %d", id); + if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN) + success = session_input_channel_req(c, rtype); + if (reply) { + packet_start(success ? + SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); + packet_put_int(c->remote_id); + packet_send(); + } + xfree(rtype); +} + +static void server_init_dispatch_20(void) { debug("server_init_dispatch_20"); @@ -964,7 +1032,7 @@ dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open); dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); + dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); /* client_alive */ @@ -972,7 +1040,7 @@ /* rekeying */ dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); } -void +static void server_init_dispatch_13(void) { debug("server_init_dispatch_13"); @@ -987,7 +1055,7 @@ dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); } -void +static void server_init_dispatch_15(void) { server_init_dispatch_13(); @@ -995,7 +1063,7 @@ dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose); } -void +static void server_init_dispatch(void) { if (compat20) @@ -1005,4 +1073,3 @@ else server_init_dispatch_15(); } - Index: src/crypto/openssh/serverloop.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/serverloop.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 serverloop.h --- src/crypto/openssh/serverloop.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/serverloop.h 30 Jun 2002 11:38:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.h,v 1.2 2001/01/29 01:58:17 niklas Exp $ */ +/* $OpenBSD: serverloop.h,v 1.5 2001/06/27 02:12:53 markus Exp $ */ /* * Author: Tatu Ylonen @@ -18,5 +18,10 @@ * (of the child program), and reads from stdout and stderr (of the child * program). */ -void server_loop(pid_t pid, int fdin, int fdout, int fderr); -void server_loop2(void); +#ifndef SERVERLOOP_H +#define SERVERLOOP_H + +void server_loop(pid_t, int, int, int); +void server_loop2(Authctxt *); + +#endif Index: src/crypto/openssh/session.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/session.c,v retrieving revision 1.4.2.12 diff -u -u -r1.4.2.12 session.c --- src/crypto/openssh/session.c 23 May 2002 22:55:52 -0000 1.4.2.12 +++ src/crypto/openssh/session.c 30 Jun 2002 11:38:00 -0000 @@ -9,7 +9,7 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 support by Markus Friedl. - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,8 +33,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.80 2001/06/04 21:59:43 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/session.c,v 1.4.2.12 2002/05/23 22:55:52 des Exp $"); +RCSID("$OpenBSD: session.c,v 1.142 2002/06/26 13:49:26 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/session.c,v 1.34 2002/06/29 11:48:58 des Exp $"); #include "ssh.h" #include "ssh1.h" @@ -47,7 +47,6 @@ #include "uidswap.h" #include "compat.h" #include "channels.h" -#include "nchan.h" #include "bufaux.h" #include "auth.h" #include "auth-options.h" @@ -58,60 +57,36 @@ #include "serverloop.h" #include "canohost.h" #include "session.h" +#include "monitor_wrap.h" -#ifdef __FreeBSD__ -#define _PATH_CHPASS "/usr/bin/passwd" -#endif /* __FreeBSD__ */ - -#ifdef HAVE_LOGIN_CAP -#include -#endif - -#ifdef KRB5 -extern krb5_context ssh_context; +#ifdef HAVE_CYGWIN +#include +#include +#define is_winnt (GetVersion() < 0x80000000) #endif -/* types */ - -#define TTYSZ 64 -typedef struct Session Session; -struct Session { - int used; - int self; - struct passwd *pw; - pid_t pid; - /* tty */ - char *term; - int ptyfd, ttyfd, ptymaster; - int row, col, xpixel, ypixel; - char tty[TTYSZ]; - /* X11 */ - char *display; - int screen; - char *auth_proto; - char *auth_data; - int single_connection; - /* proto 2 */ - int chanid; - int is_subsystem; -}; - /* func */ Session *session_new(void); -void session_set_fds(Session *s, int fdin, int fdout, int fderr); -void session_pty_cleanup(Session *s); -void session_proctitle(Session *s); -void do_exec_pty(Session *s, const char *command); -void do_exec_no_pty(Session *s, const char *command); -void do_login(Session *s, const char *command); -void do_child(Session *s, const char *command); +void session_set_fds(Session *, int, int, int); +void session_pty_cleanup(void *); +void session_proctitle(Session *); +int session_setup_x11fwd(Session *); +void do_exec_pty(Session *, const char *); +void do_exec_no_pty(Session *, const char *); +void do_exec(Session *, const char *); +void do_login(Session *, const char *); +#ifdef LOGIN_NEEDS_UTMPX +static void do_pre_login(Session *s); +#endif +void do_child(Session *, const char *); void do_motd(void); -int check_quietlogin(Session *s, const char *command); -void xauthfile_cleanup_proc(void *pw); +int check_quietlogin(Session *, const char *); -void do_authenticated1(Authctxt *authctxt); -void do_authenticated2(Authctxt *authctxt); +static void do_authenticated1(Authctxt *); +static void do_authenticated2(Authctxt *); + +static int session_pty_req(Session *); /* import */ extern ServerOptions options; @@ -122,20 +97,108 @@ extern int startup_pipe; extern void destroy_sensitive_data(void); -/* Local Xauthority file. */ -static char *xauthfile; - /* original command from peer. */ -char *original_command = NULL; +const char *original_command = NULL; /* data */ #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; +#ifdef WITH_AIXAUTHENTICATE +char *aixloginmsg; +#endif /* WITH_AIXAUTHENTICATE */ + #ifdef HAVE_LOGIN_CAP -static login_cap_t *lc; +login_cap_t *lc; #endif +/* Name and directory of socket for authentication agent forwarding. */ +static char *auth_sock_name = NULL; +static char *auth_sock_dir = NULL; + +/* removes the agent forwarding socket */ + +static void +auth_sock_cleanup_proc(void *_pw) +{ + struct passwd *pw = _pw; + + if (auth_sock_name != NULL) { + temporarily_use_uid(pw); + unlink(auth_sock_name); + rmdir(auth_sock_dir); + auth_sock_name = NULL; + restore_uid(); + } +} + +static int +auth_input_request_forwarding(struct passwd * pw) +{ + Channel *nc; + int sock; + struct sockaddr_un sunaddr; + + if (auth_sock_name != NULL) { + error("authentication forwarding requested twice."); + return 0; + } + + /* Temporarily drop privileged uid for mkdir/bind. */ + temporarily_use_uid(pw); + + /* Allocate a buffer for the socket name, and format the name. */ + auth_sock_name = xmalloc(MAXPATHLEN); + auth_sock_dir = xmalloc(MAXPATHLEN); + strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); + + /* Create private directory for socket */ + if (mkdtemp(auth_sock_dir) == NULL) { + packet_send_debug("Agent forwarding disabled: " + "mkdtemp() failed: %.100s", strerror(errno)); + restore_uid(); + xfree(auth_sock_name); + xfree(auth_sock_dir); + auth_sock_name = NULL; + auth_sock_dir = NULL; + return 0; + } + snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld", + auth_sock_dir, (long) getpid()); + + /* delete agent socket on fatal() */ + fatal_add_cleanup(auth_sock_cleanup_proc, pw); + + /* 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; + strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); + + if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) + packet_disconnect("bind: %.100s", strerror(errno)); + + /* Restore the privileged uid. */ + restore_uid(); + + /* Start listening on the socket. */ + if (listen(sock, 5) < 0) + packet_disconnect("listen: %.100s", strerror(errno)); + + /* Allocate a channel for the authentication agent socket. */ + nc = channel_new("auth socket", + SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, + 0, xstrdup("auth socket"), 1); + strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); + return 1; +} + + void do_authenticated(Authctxt *authctxt) { @@ -148,18 +211,14 @@ close(startup_pipe); startup_pipe = -1; } -#ifdef HAVE_LOGIN_CAP - if ((lc = login_getpwclass(authctxt->pw)) == NULL) { - error("unable to get login class"); - return; - } -#ifdef BSD_AUTH - if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) { - packet_disconnect("Approval failure for %s", - authctxt->pw->pw_name); - } -#endif -#endif +#ifdef WITH_AIXAUTHENTICATE + /* We don't have a pty yet, so just label the line as "ssh" */ + if (loginsuccess(authctxt->user, + get_canonical_hostname(options.verify_reverse_mapping), + "ssh", &aixloginmsg) < 0) + aixloginmsg = NULL; +#endif /* WITH_AIXAUTHENTICATE */ + /* setup the channel layer */ if (!no_port_forwarding_flag && options.allow_tcp_forwarding) channel_permit_all_opens(); @@ -169,56 +228,17 @@ else do_authenticated1(authctxt); - /* remote user's local Xauthority file and agent socket */ - if (xauthfile) - xauthfile_cleanup_proc(authctxt->pw); - if (auth_get_socket_name()) + /* remove agent socket */ + if (auth_sock_name != NULL) auth_sock_cleanup_proc(authctxt->pw); -} - -/* - * Remove local Xauthority file. - */ -void -xauthfile_cleanup_proc(void *_pw) -{ - struct passwd *pw = _pw; - char *p; - - debug("xauthfile_cleanup_proc called"); - if (xauthfile != NULL) { - temporarily_use_uid(pw); - unlink(xauthfile); - p = strrchr(xauthfile, '/'); - if (p != NULL) { - *p = '\0'; - rmdir(xauthfile); - } - xfree(xauthfile); - xauthfile = NULL; - restore_uid(); - } -} - -/* - * Function to perform cleanup if we get aborted abnormally (e.g., due to a - * dropped connection). - */ -void -pty_cleanup_proc(void *session) -{ - Session *s=session; - if (s == NULL) - fatal("pty_cleanup_proc: no session"); - debug("pty_cleanup_proc: %s", s->tty); - - if (s->pid != 0) { - /* Record that the user has logged out. */ - record_logout(s->pid, s->tty); - } - - /* Release the pseudo-tty. */ - pty_release(s->tty); +#ifdef KRB4 + if (options.kerberos_ticket_cleanup) + krb4_cleanup_proc(authctxt); +#endif +#ifdef KRB5 + if (options.kerberos_ticket_cleanup) + krb5_cleanup_proc(authctxt); +#endif } /* @@ -227,17 +247,17 @@ * terminals are allocated, X11, TCP/IP, and authentication agent forwardings * are requested, etc. */ -void +static void do_authenticated1(Authctxt *authctxt) { Session *s; char *command; - int success, type, fd, n_bytes, plen, screen_flag, have_pty = 0; - int compression_level = 0, enable_compression_after_reply = 0; - u_int proto_len, data_len, dlen; - struct stat st; + int success, type, screen_flag; + int enable_compression_after_reply = 0; + u_int proto_len, data_len, dlen, compression_level = 0; s = session_new(); + s->authctxt = authctxt; s->pw = authctxt->pw; /* @@ -248,16 +268,20 @@ success = 0; /* Get a packet from the client. */ - type = packet_read(&plen); + type = packet_read(); /* Process the packet. */ switch (type) { case SSH_CMSG_REQUEST_COMPRESSION: - packet_integrity_check(plen, 4, type); compression_level = packet_get_int(); + packet_check_eom(); if (compression_level < 1 || compression_level > 9) { packet_send_debug("Received illegal compression level %d.", - compression_level); + compression_level); + break; + } + if (!options.compression) { + debug2("compression disabled"); break; } /* Enable compression after we have responded with SUCCESS. */ @@ -266,71 +290,10 @@ break; case SSH_CMSG_REQUEST_PTY: - if (no_pty_flag) { - debug("Allocating a pty not permitted for this authentication."); - break; - } - if (have_pty) - packet_disconnect("Protocol error: you already have a pty."); - - debug("Allocating pty."); - - /* Allocate a pty and open it. */ - if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, - sizeof(s->tty))) { - error("Failed to allocate pty."); - break; - } - fatal_add_cleanup(pty_cleanup_proc, (void *)s); - pty_setowner(s->pw, s->tty); - - /* Get TERM from the packet. Note that the value may be of arbitrary length. */ - s->term = packet_get_string(&dlen); - packet_integrity_check(dlen, strlen(s->term), type); - /* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */ - /* Remaining bytes */ - n_bytes = plen - (4 + dlen + 4 * 4); - - if (strcmp(s->term, "") == 0) { - xfree(s->term); - s->term = NULL; - } - /* Get window size from the packet. */ - s->row = packet_get_int(); - s->col = packet_get_int(); - s->xpixel = packet_get_int(); - s->ypixel = packet_get_int(); - pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); - - /* Get tty modes from the packet. */ - tty_parse_modes(s->ttyfd, &n_bytes); - packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type); - - session_proctitle(s); - - /* Indicate that we now have a pty. */ - success = 1; - have_pty = 1; + success = session_pty_req(s); break; case SSH_CMSG_X11_REQUEST_FORWARDING: - if (!options.x11_forwarding) { - packet_send_debug("X11 forwarding disabled in server configuration file."); - break; - } - if (!options.xauth_location || - (stat(options.xauth_location, &st) == -1)) { - packet_send_debug("No xauth program; cannot forward with spoofing."); - break; - } - if (no_x11_forwarding_flag) { - packet_send_debug("X11 forwarding not permitted for this authentication."); - break; - } - debug("Received request for X11 forwarding with auth spoofing."); - if (s->display != NULL) - packet_disconnect("Protocol error: X11 display already set."); - s->auth_proto = packet_get_string(&proto_len); s->auth_data = packet_get_string(&data_len); @@ -342,39 +305,18 @@ if (!screen_flag) debug2("Buggy client: " "X11 screen flag missing"); - packet_integrity_check(plen, - 4 + proto_len + 4 + data_len + 4, type); s->screen = packet_get_int(); } else { - packet_integrity_check(plen, - 4 + proto_len + 4 + data_len, type); s->screen = 0; } - s->display = x11_create_display_inet(s->screen, options.x11_display_offset); - - if (s->display == NULL) - break; - - /* Setup to always have a local .Xauthority. */ - xauthfile = xmalloc(MAXPATHLEN); - strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); - temporarily_use_uid(s->pw); - if (mkdtemp(xauthfile) == NULL) { - restore_uid(); - error("private X11 dir: mkdtemp %s failed: %s", - xauthfile, strerror(errno)); - xfree(xauthfile); - xauthfile = NULL; - /* XXXX remove listening channels */ - break; + packet_check_eom(); + success = session_setup_x11fwd(s); + if (!success) { + xfree(s->auth_proto); + xfree(s->auth_data); + s->auth_proto = NULL; + s->auth_data = NULL; } - strlcat(xauthfile, "/cookies", MAXPATHLEN); - fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); - if (fd >= 0) - close(fd); - restore_uid(); - fatal_add_cleanup(xauthfile_cleanup_proc, s->pw); - success = 1; break; case SSH_CMSG_AGENT_REQUEST_FORWARDING: @@ -405,28 +347,70 @@ success = 1; break; +#if defined(AFS) || defined(KRB5) + case SSH_CMSG_HAVE_KERBEROS_TGT: + if (!options.kerberos_tgt_passing) { + verbose("Kerberos TGT passing disabled."); + } else { + char *kdata = packet_get_string(&dlen); + packet_check_eom(); + + /* XXX - 0x41, see creds_to_radix version */ + if (kdata[0] != 0x41) { +#ifdef KRB5 + krb5_data tgt; + tgt.data = kdata; + tgt.length = dlen; + + if (auth_krb5_tgt(s->authctxt, &tgt)) + success = 1; + else + verbose("Kerberos v5 TGT refused for %.100s", s->authctxt->user); +#endif /* KRB5 */ + } else { +#ifdef AFS + if (auth_krb4_tgt(s->authctxt, kdata)) + success = 1; + else + verbose("Kerberos v4 TGT refused for %.100s", s->authctxt->user); +#endif /* AFS */ + } + xfree(kdata); + } + break; +#endif /* AFS || KRB5 */ + +#ifdef AFS + case SSH_CMSG_HAVE_AFS_TOKEN: + if (!options.afs_token_passing || !k_hasafs()) { + verbose("AFS token passing disabled."); + } else { + /* Accept AFS token. */ + char *token = packet_get_string(&dlen); + packet_check_eom(); + + if (auth_afs_token(s->authctxt, token)) + success = 1; + else + verbose("AFS token refused for %.100s", + s->authctxt->user); + xfree(token); + } + break; +#endif /* AFS */ + case SSH_CMSG_EXEC_SHELL: case SSH_CMSG_EXEC_CMD: if (type == SSH_CMSG_EXEC_CMD) { command = packet_get_string(&dlen); debug("Exec command '%.500s'", command); - packet_integrity_check(plen, 4 + dlen, type); + do_exec(s, command); + xfree(command); } else { - command = NULL; - packet_integrity_check(plen, 0, type); + do_exec(s, NULL); } - if (forced_command != NULL) { - original_command = command; - command = forced_command; - debug("Forced command '%.500s'", forced_command); - } - if (have_pty) - do_exec_pty(s, command); - else - do_exec_no_pty(s, command); - - if (command != NULL) - xfree(command); + packet_check_eom(); + session_close(s); return; default: @@ -456,7 +440,7 @@ void do_exec_no_pty(Session *s, const char *command) { - int pid; + pid_t pid; #ifdef USE_PIPES int pin[2], pout[2], perr[2]; @@ -477,8 +461,12 @@ session_proctitle(s); -#ifdef USE_PAM - do_pam_setcred(); +#if defined(USE_PAM) + do_pam_session(s->pw->pw_name, NULL); + do_pam_setcred(1); + if (is_pam_password_change_required()) + packet_disconnect("Password change required but no " + "TTY available"); #endif /* USE_PAM */ /* Fork the child. */ @@ -534,6 +522,10 @@ do_child(s, command); /* NOTREACHED */ } +#ifdef HAVE_CYGWIN + if (is_winnt) + cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); +#endif if (pid < 0) packet_disconnect("fork failed: %.100s", strerror(errno)); s->pid = pid; @@ -587,45 +579,51 @@ ptyfd = s->ptyfd; ttyfd = s->ttyfd; -#ifdef USE_PAM +#if defined(USE_PAM) do_pam_session(s->pw->pw_name, s->tty); - do_pam_setcred(); -#endif /* USE_PAM */ + do_pam_setcred(1); +#endif /* Fork the child. */ if ((pid = fork()) == 0) { + /* Child. Reinitialize the log because the pid has changed. */ log_init(__progname, options.log_level, options.log_facility, log_stderr); - /* Close the master side of the pseudo tty. */ close(ptyfd); /* Make the pseudo tty our controlling tty. */ pty_make_controlling_tty(&ttyfd, s->tty); - /* 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)); + /* Redirect stdin/stdout/stderr from the pseudo tty. */ + if (dup2(ttyfd, 0) < 0) + error("dup2 stdin: %s", strerror(errno)); + if (dup2(ttyfd, 1) < 0) + error("dup2 stdout: %s", strerror(errno)); + if (dup2(ttyfd, 2) < 0) + error("dup2 stderr: %s", strerror(errno)); /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); /* record login, etc. similar to login(1) */ +#ifndef HAVE_OSF_SIA if (!(options.use_login && command == NULL)) do_login(s, command); +# ifdef LOGIN_NEEDS_UTMPX + else + do_pre_login(s); +# endif +#endif /* Do common processing for the child, such as execing the command. */ do_child(s, command); /* NOTREACHED */ } +#ifdef HAVE_CYGWIN + if (is_winnt) + cygwin_set_impersonation_token(INVALID_HANDLE_VALUE); +#endif if (pid < 0) packet_disconnect("fork failed: %.100s", strerror(errno)); s->pid = pid; @@ -655,31 +653,68 @@ } else { server_loop(pid, ptyfd, fdout, -1); /* server_loop _has_ closed ptyfd and fdout. */ - session_pty_cleanup(s); } } +#ifdef LOGIN_NEEDS_UTMPX +static void +do_pre_login(Session *s) +{ + socklen_t fromlen; + struct sockaddr_storage from; + pid_t pid = getpid(); + + /* + * Get IP address of client. If the connection is not a socket, let + * the address be 0.0.0.0. + */ + memset(&from, 0, sizeof(from)); + if (packet_connection_is_on_socket()) { + fromlen = sizeof(from); + if (getpeername(packet_get_connection_in(), + (struct sockaddr *) & from, &fromlen) < 0) { + debug("getpeername: %.100s", strerror(errno)); + fatal_cleanup(); + } + } + + record_utmp_only(pid, s->tty, s->pw->pw_name, + get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), + (struct sockaddr *)&from); +} +#endif + +/* + * This is called to fork and execute a command. If another command is + * to be forced, execute that instead. + */ +void +do_exec(Session *s, const char *command) +{ + if (forced_command) { + original_command = command; + command = forced_command; + debug("Forced command '%.900s'", command); + } + + if (s->ttyfd != -1) + do_exec_pty(s, command); + else + do_exec_no_pty(s, command); + + original_command = NULL; +} + + /* administrative, login(1)-like work */ void do_login(Session *s, const char *command) { - FILE *f; - char *time_string, *newcommand; - char buf[256]; - char hostname[MAXHOSTNAMELEN]; + char *time_string; socklen_t fromlen; struct sockaddr_storage from; - time_t last_login_time; struct passwd * pw = s->pw; pid_t pid = getpid(); -#ifdef HAVE_LOGIN_CAP - char *fname; -#endif /* HAVE_LOGIN_CAP */ -#ifdef __FreeBSD__ -#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ - struct timeval tv; - time_t warntime = DEFAULT_WARN; -#endif /* __FreeBSD__ */ /* * Get IP address of client. If the connection is not a socket, let @@ -689,145 +724,54 @@ if (packet_connection_is_on_socket()) { fromlen = sizeof(from); if (getpeername(packet_get_connection_in(), - (struct sockaddr *) & from, &fromlen) < 0) { + (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); fatal_cleanup(); } } - /* Get the time and hostname when the user last logged in. */ - if (options.print_lastlog) { - hostname[0] = '\0'; - last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, - hostname, sizeof(hostname)); - } - /* Record that there was a login on that tty from the remote host. */ - record_login(pid, s->tty, pw->pw_name, pw->pw_uid, - get_remote_name_or_ip(utmp_len, options.reverse_mapping_check), - (struct sockaddr *)&from); + if (!use_privsep) + record_login(pid, s->tty, pw->pw_name, pw->pw_uid, + get_remote_name_or_ip(utmp_len, + options.verify_reverse_mapping), + (struct sockaddr *)&from); #ifdef USE_PAM /* * If password change is needed, do it now. * This needs to occur before the ~/.hushlogin check. */ - if (pam_password_change_required()) { + if (is_pam_password_change_required()) { print_pam_messages(); do_pam_chauthtok(); } #endif + if (check_quietlogin(s, command)) + return; + #ifdef USE_PAM - if (!check_quietlogin(s, command) && !pam_password_change_required()) + if (!is_pam_password_change_required()) print_pam_messages(); #endif /* USE_PAM */ +#ifdef WITH_AIXAUTHENTICATE + if (aixloginmsg && *aixloginmsg) + printf("%s\n", aixloginmsg); +#endif /* WITH_AIXAUTHENTICATE */ -#ifdef __FreeBSD__ - if (pw->pw_change || pw->pw_expire) - (void)gettimeofday(&tv, NULL); -#ifdef HAVE_LOGIN_CAP - warntime = login_getcaptime(lc, "warnpassword", - DEFAULT_WARN, DEFAULT_WARN); -#endif /* HAVE_LOGIN_CAP */ - /* - * If the password change time is set and has passed, give the - * user a password expiry notice and chance to change it. - */ - if (pw->pw_change != 0) { - if (tv.tv_sec >= pw->pw_change) { - (void)printf( - "Sorry -- your password has expired.\n"); - log("%s Password expired - forcing change", - pw->pw_name); - if (newcommand != NULL) - xfree(newcommand); - newcommand = xstrdup(_PATH_CHPASS); - } else if (pw->pw_change - tv.tv_sec < warntime && - !check_quietlogin(s, command)) - (void)printf( - "Warning: your password expires on %s", - ctime(&pw->pw_change)); - } -#ifdef HAVE_LOGIN_CAP - warntime = login_getcaptime(lc, "warnexpire", - DEFAULT_WARN, DEFAULT_WARN); -#endif /* HAVE_LOGIN_CAP */ -#ifndef USE_PAM - if (pw->pw_expire) { - if (tv.tv_sec >= pw->pw_expire) { - (void)printf( - "Sorry -- your account has expired.\n"); - log( - "LOGIN %.200s REFUSED (EXPIRED) FROM %.200s ON TTY %.200s", - pw->pw_name, get_remote_name_or_ip(utmp_len, - options.reverse_mapping_check), s->tty); - exit(254); - } else if (pw->pw_expire - tv.tv_sec < warntime && - !check_quietlogin(s, command)) - (void)printf( - "Warning: your account expires on %s", - ctime(&pw->pw_expire)); - } -#endif /* !USE_PAM */ -#endif /* __FreeBSD__ */ - -#ifdef HAVE_LOGIN_CAP - if (!auth_ttyok(lc, s->tty)) { - (void)printf("Permission denied.\n"); - log( - "LOGIN %.200s REFUSED (TTY) FROM %.200s ON TTY %.200s", - pw->pw_name, get_remote_name_or_ip(utmp_len, - options.reverse_mapping_check), s->tty); - exit(254); - } -#endif /* HAVE_LOGIN_CAP */ - - /* - * 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). Login(1) will do this for - * us as well, so check if login(1) is used - */ - if (command == NULL && options.print_lastlog && - last_login_time != 0 && !check_quietlogin(s, command) && - !options.use_login) { - time_string = ctime(&last_login_time); - /* Remove the trailing newline. */ + if (options.print_lastlog && s->last_login_time != 0) { + time_string = ctime(&s->last_login_time); if (strchr(time_string, '\n')) *strchr(time_string, '\n') = 0; - if (strcmp(hostname, "") == 0) + if (strcmp(s->hostname, "") == 0) printf("Last login: %s\r\n", time_string); else - printf("Last login: %s from %s\r\n", time_string, hostname); - } - -#ifdef HAVE_LOGIN_CAP - if (command == NULL && !check_quietlogin(s, command) && - !options.use_login) { - fname = login_getcapstr(lc, "copyright", NULL, NULL); - if (fname != NULL && (f = fopen(fname, "r")) != NULL) { - while (fgets(buf, sizeof(buf), f) != NULL) - fputs(buf, stdout); - fclose(f); - } else - (void)printf("%s\n\t%s %s\n", - "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994", - "The Regents of the University of California. ", - "All rights reserved."); + printf("Last login: %s from %s\r\n", time_string, + s->hostname); } -#endif /* HAVE_LOGIN_CAP */ - /* - * Print /etc/motd unless a command was specified or printing - * it was disabled in server options or login(1) will be - * used. Note that some machines appear to print it in - * /etc/profile or similar. - */ - if (command == NULL && !check_quietlogin(s, command) && !options.use_login) - do_motd(); + do_motd(); } /* @@ -843,9 +787,9 @@ #ifdef HAVE_LOGIN_CAP f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", "/etc/motd"), "r"); -#else /* !HAVE_LOGIN_CAP */ +#else f = fopen("/etc/motd", "r"); -#endif /* HAVE_LOGIN_CAP */ +#endif if (f) { while (fgets(buf, sizeof(buf), f)) fputs(buf, stdout); @@ -854,6 +798,7 @@ } } + /* * Check for quiet login, either .hushlogin or command given. */ @@ -861,7 +806,7 @@ check_quietlogin(Session *s, const char *command) { char buf[256]; - struct passwd * pw = s->pw; + struct passwd *pw = s->pw; struct stat st; /* Return 1 if .hushlogin exists or a command given. */ @@ -882,9 +827,9 @@ * Sets the value of the given variable in the environment. If the variable * already exists, its value is overriden. */ -void +static void child_set_env(char ***envp, u_int *envsizep, const char *name, - const char *value) + const char *value) { u_int i, namelen; char **env; @@ -905,6 +850,9 @@ } else { /* New variable. Expand if necessary. */ if (i >= (*envsizep) - 1) { + if (*envsizep >= 1000) + fatal("child_set_env: too many env vars," + " skipping: %.100s", name); (*envsizep) += 50; env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *)); } @@ -923,19 +871,22 @@ * Otherwise, it must consist of empty lines, comments (line starts with '#') * and assignments of the form name=value. No other forms are allowed. */ -void +static void read_environment_file(char ***env, u_int *envsize, - const char *filename) + const char *filename) { FILE *f; char buf[4096]; char *cp, *value; + u_int lineno = 0; f = fopen(filename, "r"); if (!f) return; while (fgets(buf, sizeof(buf), f)) { + if (++lineno > 1000) + fatal("Too many lines in environment file %s", filename); for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '#' || *cp == '\n') @@ -944,7 +895,8 @@ *strchr(cp, '\n') = '\0'; value = strchr(cp, '='); if (value == NULL) { - fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); + fprintf(stderr, "Bad line %u in %.100s\n", lineno, + filename); continue; } /* @@ -958,220 +910,118 @@ fclose(f); } -#ifdef USE_PAM -/* - * Sets any environment variables which have been specified by PAM - */ -void do_pam_environment(char ***env, int *envsize) +void copy_environment(char **source, char ***env, u_int *envsize) { - char *equals, var_name[512], var_val[512]; - char **pam_env; + char *var_name, *var_val; int i; - if ((pam_env = fetch_pam_environment()) == NULL) + if (source == NULL) return; - - for(i = 0; pam_env[i] != NULL; i++) { - if ((equals = strstr(pam_env[i], "=")) == NULL) - continue; - - if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) { - memset(var_name, '\0', sizeof(var_name)); - memset(var_val, '\0', sizeof(var_val)); - - strncpy(var_name, pam_env[i], equals - pam_env[i]); - strcpy(var_val, equals + 1); - child_set_env(env, envsize, var_name, var_val); + for(i = 0; source[i] != NULL; i++) { + var_name = xstrdup(source[i]); + if ((var_val = strstr(var_name, "=")) == NULL) { + xfree(var_name); + continue; } + *var_val++ = '\0'; + + debug3("Copy environment: %s=%s", var_name, var_val); + child_set_env(env, envsize, var_name, var_val); + + xfree(var_name); } } -#endif /* USE_PAM */ - -/* - * 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(Session *s, const char *command) +static char ** +do_setup_env(Session *s, const char *shell) { - const char *shell, *hostname = NULL, *cp = NULL; - struct passwd * pw = s->pw; char buf[256]; - char cmd[1024]; - FILE *f = NULL; - u_int envsize, i; - char **env = NULL; + u_int i, envsize; + char **env; +#ifdef HAVE_LOGIN_CAP extern char **environ; - struct stat st; - char *argv[10]; - int do_xauth = s->auth_proto != NULL && s->auth_data != NULL; + char **senv, **var; +#endif + struct passwd *pw = s->pw; - /* remove hostkey from the child's memory */ - destroy_sensitive_data(); + /* Initialize the environment. */ + envsize = 100; + env = xmalloc(envsize * sizeof(char *)); + env[0] = NULL; - /* login(1) is only called if we execute the login shell */ - if (options.use_login && command != NULL) - options.use_login = 0; - -#ifndef USE_PAM - if (!options.use_login) { -#ifdef HAVE_LOGIN_CAP - if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) - f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, - _PATH_NOLOGIN), "r"); -#else - if (pw->pw_uid) - f = fopen(_PATH_NOLOGIN, "r"); -#endif - if (f) { - /* /etc/nologin exists. Print its contents and exit. */ - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stderr); - fclose(f); - exit(254); - } - } -#endif /* !USE_PAM */ - /* Set login name, uid, gid, and groups. */ - /* Login(1) does this as well, and it needs uid 0 for the "-h" - switch, so we let login(1) to this for us. */ - if (!options.use_login) { -#ifdef HAVE_LOGIN_CAP - char **tmpenv; - - /* Initialize temp environment */ - envsize = 64; - env = xmalloc(envsize * sizeof(char *)); - env[0] = NULL; - - child_set_env(&env, &envsize, "PATH", - (pw->pw_uid == 0) ? - _PATH_STDPATH : _PATH_DEFPATH); - - snprintf(buf, sizeof buf, "%.200s/%.50s", - _PATH_MAILDIR, pw->pw_name); - child_set_env(&env, &envsize, "MAIL", buf); - - if (getenv("TZ")) - child_set_env(&env, &envsize, "TZ", getenv("TZ")); - - /* Save parent environment */ - tmpenv = environ; - environ = env; - - if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETALL) < 0) - fatal("setusercontext failed: %s", strerror(errno)); - - /* Restore parent environment */ - env = environ; - environ = tmpenv; - - for (envsize = 0; env[envsize] != NULL; ++envsize) - ; - envsize = (envsize < 100) ? 100 : envsize + 16; - env = xrealloc(env, envsize * sizeof(char *)); - -#endif /* !HAVE_LOGIN_CAP */ - if (getuid() == 0 || geteuid() == 0) { -#ifdef HAVE_LOGIN_CAP - if (setusercontext(lc, pw, pw->pw_uid, - (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { - perror("unable to set user context"); - exit(1); - } -#else - if (setlogin(pw->pw_name) < 0) - error("setlogin failed: %s", strerror(errno)); - if (setgid(pw->pw_gid) < 0) { - perror("setgid"); - exit(1); - } - /* Initialize the group list. */ - if (initgroups(pw->pw_name, pw->pw_gid) < 0) { - perror("initgroups"); - exit(1); - } - endgrent(); - - /* Permanently switch to the desired uid. */ - permanently_set_uid(pw); -#endif /* HAVE_LOGIN_CAP */ - } - if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) - fatal("Failed to set uids to %u.", (u_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') ? _PATH_BSHELL : pw->pw_shell; -#ifdef HAVE_LOGIN_CAP - shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); -#endif - -#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. */ - if (env == NULL) { - envsize = 100; - env = xmalloc(envsize * sizeof(char *)); - env[0] = NULL; - } +#ifdef HAVE_CYGWIN + /* + * The Windows environment contains some setting which are + * important for a running system. They must not be dropped. + */ + copy_environment(environ, &env, &envsize); +#endif + if (getenv("TZ")) + child_set_env(&env, &envsize, "TZ", getenv("TZ")); if (!options.use_login) { /* 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); -#ifdef HAVE_LOGIN_CAP - (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH); - child_set_env(&env, &envsize, "PATH", getenv("PATH")); -#else - child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); -#endif - snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); child_set_env(&env, &envsize, "MAIL", buf); +#ifdef HAVE_LOGIN_CAP + child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); + child_set_env(&env, &envsize, "TERM", "su"); + senv = environ; + environ = xmalloc(sizeof(char *)); + *environ = NULL; + (void) setusercontext(lc, pw, pw->pw_uid, + LOGIN_SETENV|LOGIN_SETPATH); + copy_environment(environ, &env, &envsize); + for (var = environ; *var != NULL; ++var) + xfree(*var); + xfree(environ); + environ = senv; +#else /* HAVE_LOGIN_CAP */ +# ifndef HAVE_CYGWIN + /* + * There's no standard path on Windows. The path contains + * important components pointing to the system directories, + * needed for loading shared libraries. So the path better + * remains intact here. + */ +# ifdef SUPERUSER_PATH + child_set_env(&env, &envsize, "PATH", + s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH); +# else + child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); +# endif /* SUPERUSER_PATH */ +# endif /* HAVE_CYGWIN */ +#endif /* HAVE_LOGIN_CAP */ /* Normal systems set SHELL by default. */ child_set_env(&env, &envsize, "SHELL", shell); } - if (getenv("TZ")) - child_set_env(&env, &envsize, "TZ", getenv("TZ")); /* Set custom environment options from RSA authentication. */ if (!options.use_login) { - 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); - } + while (custom_environment) { + struct envstring *ce = custom_environment; + char *s = ce->s; + + 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); + } } snprintf(buf, sizeof buf, "%.50s %d %d", - get_remote_ipaddr(), get_remote_port(), get_local_port()); + get_remote_ipaddr(), get_remote_port(), get_local_port()); child_set_env(&env, &envsize, "SSH_CLIENT", buf); if (s->ttyfd != -1) @@ -1184,50 +1034,35 @@ child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", original_command); -#ifdef KRB4 +#ifdef _AIX { - extern char *ticket; + char *cp; - if (ticket) - child_set_env(&env, &envsize, "KRBTKFILE", ticket); + if ((cp = getenv("AUTHSTATE")) != NULL) + child_set_env(&env, &envsize, "AUTHSTATE", cp); + if ((cp = getenv("KRB5CCNAME")) != NULL) + child_set_env(&env, &envsize, "KRB5CCNAME", cp); + read_environment_file(&env, &envsize, "/etc/environment"); } -#endif /* KRB4 */ +#endif +#ifdef KRB4 + if (s->authctxt->krb4_ticket_file) + child_set_env(&env, &envsize, "KRBTKFILE", + s->authctxt->krb4_ticket_file); +#endif #ifdef KRB5 -{ - extern krb5_ccache mem_ccache; - - if (mem_ccache) { - krb5_error_code problem; - krb5_ccache ccache; -#ifdef AFS - if (k_hasafs()) - krb5_afslog(ssh_context, mem_ccache, NULL, NULL); -#endif /* AFS */ - - problem = krb5_cc_default(ssh_context, &ccache); - if (problem) {} - else { - problem = krb5_cc_copy_cache(ssh_context, mem_ccache, ccache); - if (problem) {} - } - - krb5_cc_close(ssh_context, ccache); - } - - krb5_cleanup_proc(NULL); - } -#endif /* KRB5 */ - + if (s->authctxt->krb5_ticket_file) + child_set_env(&env, &envsize, "KRB5CCNAME", + s->authctxt->krb5_ticket_file); +#endif #ifdef USE_PAM /* Pull in any environment variables that may have been set by PAM. */ - do_pam_environment(&env, &envsize); + copy_environment(fetch_pam_environment(), &env, &envsize); #endif /* USE_PAM */ - if (xauthfile) - child_set_env(&env, &envsize, "XAUTHORITY", xauthfile); - if (auth_get_socket_name() != NULL) + if (auth_sock_name != NULL) child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, - auth_get_socket_name()); + auth_sock_name); /* read $HOME/.ssh/environment. */ if (!options.use_login) { @@ -1241,10 +1076,237 @@ for (i = 0; env[i]; i++) fprintf(stderr, " %.200s\n", env[i]); } + return env; +} + +/* + * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found + * first in this order). + */ +static void +do_rc_files(Session *s, const char *shell) +{ + FILE *f = NULL; + char cmd[1024]; + int do_xauth; + struct stat st; + + do_xauth = + s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; + + /* ignore _PATH_SSH_USER_RC for subsystems */ + if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) { + snprintf(cmd, sizeof cmd, "%s -c '%s %s'", + shell, _PATH_BSHELL, _PATH_SSH_USER_RC); + if (debug_flag) + fprintf(stderr, "Running %s\n", cmd); + f = popen(cmd, "w"); + if (f) { + if (do_xauth) + fprintf(f, "%s %s\n", s->auth_proto, + s->auth_data); + pclose(f); + } else + fprintf(stderr, "Could not run %s\n", + _PATH_SSH_USER_RC); + } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { + if (debug_flag) + fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, + _PATH_SSH_SYSTEM_RC); + f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); + if (f) { + if (do_xauth) + fprintf(f, "%s %s\n", s->auth_proto, + s->auth_data); + pclose(f); + } else + fprintf(stderr, "Could not run %s\n", + _PATH_SSH_SYSTEM_RC); + } else if (do_xauth && options.xauth_location != NULL) { + /* Add authority data to .Xauthority if appropriate. */ + if (debug_flag) { + fprintf(stderr, + "Running %.500s add " + "%.100s %.100s %.100s\n", + options.xauth_location, s->auth_display, + s->auth_proto, s->auth_data); + } + snprintf(cmd, sizeof cmd, "%s -q -", + options.xauth_location); + f = popen(cmd, "w"); + if (f) { + fprintf(f, "add %s %s %s\n", + s->auth_display, s->auth_proto, + s->auth_data); + pclose(f); + } else { + fprintf(stderr, "Could not run %s\n", + cmd); + } + } +} + +static void +do_nologin(struct passwd *pw) +{ + FILE *f = NULL; + char buf[1024]; + +#ifdef HAVE_LOGIN_CAP + if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) + f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, + _PATH_NOLOGIN), "r"); +#else + if (pw->pw_uid) + f = fopen(_PATH_NOLOGIN, "r"); +#endif + if (f) { + /* /etc/nologin exists. Print its contents and exit. */ + while (fgets(buf, sizeof(buf), f)) + fputs(buf, stderr); + fclose(f); + exit(254); + } +} + +/* Set login name, uid, gid, and groups. */ +void +do_setusercontext(struct passwd *pw) +{ + char tty='\0'; + +#ifdef HAVE_CYGWIN + if (is_winnt) { +#else /* HAVE_CYGWIN */ + if (getuid() == 0 || geteuid() == 0) { +#endif /* HAVE_CYGWIN */ +#ifdef HAVE_SETPCRED + setpcred(pw->pw_name); +#endif /* HAVE_SETPCRED */ +#ifdef HAVE_LOGIN_CAP +#ifdef __bsdi__ + setpgid(0, 0); +#endif + if (setusercontext(lc, pw, pw->pw_uid, + (LOGIN_SETALL & ~(LOGIN_SETENV|LOGIN_SETPATH))) < 0) { + perror("unable to set user context"); + exit(1); + } +#else +# if defined(HAVE_GETLUID) && defined(HAVE_SETLUID) + /* Sets login uid for accounting */ + if (getluid() == -1 && setluid(pw->pw_uid) == -1) + error("setluid: %s", strerror(errno)); +# endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */ + + if (setlogin(pw->pw_name) < 0) + error("setlogin failed: %s", strerror(errno)); + if (setgid(pw->pw_gid) < 0) { + perror("setgid"); + exit(1); + } + /* Initialize the group list. */ + if (initgroups(pw->pw_name, pw->pw_gid) < 0) { + perror("initgroups"); + exit(1); + } + endgrent(); +# ifdef USE_PAM + /* + * PAM credentials may take the form of supplementary groups. + * These will have been wiped by the above initgroups() call. + * Reestablish them here. + */ + do_pam_setcred(0); +# endif /* USE_PAM */ +# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) + irix_setusercontext(pw); +# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ +# ifdef _AIX + /* XXX: Disable tty setting. Enabled if required later */ + aix_usrinfo(pw, &tty, -1); +# endif /* _AIX */ + /* Permanently switch to the desired uid. */ + permanently_set_uid(pw); +#endif + } + if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) + fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); +} + +static void +launch_login(struct passwd *pw, const char *hostname) +{ + /* Launch login(1). */ + + execl(LOGIN_PROGRAM, "login", "-h", hostname, +#ifdef xxxLOGIN_NEEDS_TERM + (s->term ? s->term : "unknown"), +#endif /* LOGIN_NEEDS_TERM */ +#ifdef LOGIN_NO_ENDOPT + "-p", "-f", pw->pw_name, (char *)NULL); +#else + "-p", "-f", "--", pw->pw_name, (char *)NULL); +#endif + + /* Login couldn't be executed, die. */ + + perror("login"); + exit(1); +} + +/* + * 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(Session *s, const char *command) +{ + extern char **environ; + char **env; + char *argv[10]; + const char *shell, *shell0, *hostname = NULL; + struct passwd *pw = s->pw; + u_int i; + + /* remove hostkey from the child's memory */ + destroy_sensitive_data(); + + /* login(1) is only called if we execute the login shell */ + if (options.use_login && command != NULL) + options.use_login = 0; + + /* + * Login(1) does this as well, and it needs uid 0 for the "-h" + * switch, so we let login(1) to this for us. + */ + if (!options.use_login) { +#ifdef HAVE_OSF_SIA + session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty); + if (!check_quietlogin(s, command)) + do_motd(); +#else /* HAVE_OSF_SIA */ + do_nologin(pw); + do_setusercontext(pw); +#endif /* HAVE_OSF_SIA */ + } + + /* + * Get the shell from the password data. An empty shell field is + * legal, and means /bin/sh. + */ + shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; +#ifdef HAVE_LOGIN_CAP + shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); +#endif + + env = do_setup_env(s, shell); + /* we have to stash the hostname before we close our socket. */ if (options.use_login) hostname = get_remote_name_or_ip(utmp_len, - options.reverse_mapping_check); + options.verify_reverse_mapping); /* * Close the connection descriptors; note that this is the child, and * the server will still have the socket open, and it is important @@ -1272,201 +1334,91 @@ endpwent(); /* - * Restore any signal handlers set by sshd previously that should - * be restored to their initial state. - */ - signal(SIGPIPE, SIG_DFL); - - /* Change current directory to the user\'s home directory. */ - if ( -#ifdef __FreeBSD__ - !*pw->pw_dir || -#endif /* __FreeBSD__ */ - chdir(pw->pw_dir) < 0 - ) { -#ifdef HAVE_LOGIN_CAP - if (login_getcapbool(lc, "requirehome", 0)) { - (void)printf("Home directory not available\n"); - log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s", - pw->pw_name, ttyname); - exit(254); - } -#endif /* HAVE_LOGIN_CAP */ -#ifdef __FreeBSD__ - if (chdir("/") < 0) { - (void)printf("Cannot find root directory\n"); - log("LOGIN %.200s REFUSED (ROOTDIR) ON TTY %.200s", - pw->pw_name, ttyname); - exit(254); - } - if (!check_quietlogin(s, command) || *pw->pw_dir) - (void)printf( - "No home directory.\nLogging in with home = \"/\".\n"); - -#else /* !__FreeBSD__ */ - - fprintf(stderr, "Could not chdir to home directory %s: %s\n", - pw->pw_dir, strerror(errno)); -#endif /* __FreeBSD__ */ - } - - /* * 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 < getdtablesize(); i++) + for (i = 3; i < 64; i++) close(i); /* - * Must take new environment into use so that .ssh/rc, /etc/sshrc and - * xauth are run in the proper environment. + * Must take new environment into use so that .ssh/rc, + * /etc/ssh/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 (!options.use_login) { - /* ignore _PATH_SSH_USER_RC for subsystems */ - if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) { - snprintf(cmd, sizeof cmd, "%s -c '%s %s'", - shell, _PATH_BSHELL, _PATH_SSH_USER_RC); - if (debug_flag) - fprintf(stderr, "Running %s\n", cmd); - f = popen(cmd, "w"); - if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); - pclose(f); - } else - fprintf(stderr, "Could not run %s\n", - _PATH_SSH_USER_RC); - } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { - if (debug_flag) - fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, - _PATH_SSH_SYSTEM_RC); - f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); - if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); - pclose(f); - } else - fprintf(stderr, "Could not run %s\n", - _PATH_SSH_SYSTEM_RC); - } else if (do_xauth && options.xauth_location != NULL) { - /* Add authority data to .Xauthority if appropriate. */ - char *screen = strchr(s->display, ':'); - - if (debug_flag) { - fprintf(stderr, - "Running %.100s add " - "%.100s %.100s %.100s\n", - options.xauth_location, s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(stderr, - "Adding %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, s->auth_data); - } - snprintf(cmd, sizeof cmd, "%s -q -", - options.xauth_location); - f = popen(cmd, "w"); - if (f) { - fprintf(f, "add %s %s %s\n", s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(f, "add %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, - s->auth_data); - pclose(f); - } else { - fprintf(stderr, "Could not run %s\n", - cmd); - } - } - /* Get the last component of the shell name. */ - cp = strrchr(shell, '/'); - if (cp) - cp++; - else - cp = 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 */ + + /* 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)); +#ifdef HAVE_LOGIN_CAP + if (login_getcapbool(lc, "requirehome", 0)) + exit(1); +#endif } + if (!options.use_login) + do_rc_files(s, shell); + /* restore SIGPIPE for child */ signal(SIGPIPE, SIG_DFL); + if (options.use_login) { + launch_login(pw, hostname); + /* NEVERREACHED */ + } + + /* Get the last component of the shell name. */ + if ((shell0 = strrchr(shell, '/')) != NULL) + shell0++; + else + shell0 = 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) { - if (!options.use_login) { - char buf[256]; + char argv0[256]; - /* - * Check for mail if we have a tty and it was enabled - * in server options. - */ - if (s->ttyfd != -1 && options.check_mail) { - char *mailbox; - struct stat mailstat; - - mailbox = getenv("MAIL"); - if (mailbox != NULL) { - if (stat(mailbox, &mailstat) != 0 || - mailstat.st_size == 0) -#ifdef __FreeBSD__ - ; -#else /* !__FreeBSD__ */ - printf("No mail.\n"); -#endif /* __FreeBSD__ */ - else if (mailstat.st_mtime < mailstat.st_atime) - printf("You have mail.\n"); - else - printf("You have new mail.\n"); - } - } - /* 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); + /* Start the shell. Set initial character to '-'. */ + argv0[0] = '-'; - /* Executing the shell failed. */ + if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1) + >= sizeof(argv0) - 1) { + errno = EINVAL; perror(shell); exit(1); - - } else { - /* Launch login(1). */ - - execl("/usr/bin/login", "login", "-h", hostname, - "-p", "-f", "--", pw->pw_name, NULL); - - /* Login couldn't be executed, die. */ - - perror("login"); - exit(1); } + + /* Execute the shell. */ + argv[0] = argv0; + 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[0] = (char *) shell0; argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; @@ -1482,13 +1434,12 @@ static int did_init = 0; if (!did_init) { debug("session_new: init"); - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { sessions[i].used = 0; - sessions[i].self = i; } did_init = 1; } - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (! s->used) { memset(s, 0, sizeof(*s)); @@ -1496,6 +1447,7 @@ s->ptyfd = -1; s->ttyfd = -1; s->used = 1; + s->self = i; debug("session_new: session %d", i); return s; } @@ -1503,23 +1455,23 @@ return NULL; } -void +static void session_dump(void) { int i; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; - debug("dump: used %d session %d %p channel %d pid %d", + debug("dump: used %d session %d %p channel %d pid %ld", s->used, s->self, s, s->chanid, - s->pid); + (long)s->pid); } } int -session_open(int chanid) +session_open(Authctxt *authctxt, int chanid) { Session *s = session_new(); debug("session_open: channel %d", chanid); @@ -1527,7 +1479,8 @@ error("no more sessions"); return 0; } - s->pw = auth_get_user(); + s->authctxt = authctxt; + s->pw = authctxt->pw; if (s->pw == NULL) fatal("no user for session %d", s->self); debug("session_open: session %d: link with channel %d", s->self, chanid); @@ -1536,10 +1489,26 @@ } Session * +session_by_tty(char *tty) +{ + int i; + for (i = 0; i < MAX_SESSIONS; i++) { + Session *s = &sessions[i]; + if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { + debug("session_by_tty: session %d tty %s", i, tty); + return s; + } + } + debug("session_by_tty: unknown tty %.100s", tty); + session_dump(); + return NULL; +} + +static Session * session_by_channel(int id) { int i; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->chanid == id) { debug("session_by_channel: session %d channel %d", i, id); @@ -1551,46 +1520,63 @@ return NULL; } -Session * +static Session * session_by_pid(pid_t pid) { int i; - debug("session_by_pid: pid %d", pid); - for(i = 0; i < MAX_SESSIONS; i++) { + debug("session_by_pid: pid %ld", (long)pid); + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; } - error("session_by_pid: unknown pid %d", pid); + error("session_by_pid: unknown pid %ld", (long)pid); session_dump(); return NULL; } -int +static int session_window_change_req(Session *s) { s->col = packet_get_int(); s->row = packet_get_int(); s->xpixel = packet_get_int(); s->ypixel = packet_get_int(); - packet_done(); + packet_check_eom(); pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); return 1; } -int +static int session_pty_req(Session *s) { u_int len; int n_bytes; - if (no_pty_flag) + if (no_pty_flag) { + debug("Allocating a pty not permitted for this authentication."); return 0; - if (s->ttyfd != -1) + } + if (s->ttyfd != -1) { + packet_disconnect("Protocol error: you already have a pty."); return 0; + } + /* Get the time and hostname when the user last logged in. */ + if (options.print_lastlog) { + s->hostname[0] = '\0'; + s->last_login_time = get_last_login_time(s->pw->pw_uid, + s->pw->pw_name, s->hostname, sizeof(s->hostname)); + } + s->term = packet_get_string(&len); - s->col = packet_get_int(); - s->row = packet_get_int(); + + if (compat20) { + s->col = packet_get_int(); + s->row = packet_get_int(); + } else { + s->row = packet_get_int(); + s->col = packet_get_int(); + } s->xpixel = packet_get_int(); s->ypixel = packet_get_int(); @@ -1598,9 +1584,12 @@ xfree(s->term); s->term = NULL; } + /* Allocate a pty and open it. */ - if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) { - xfree(s->term); + debug("Allocating pty."); + if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { + if (s->term) + xfree(s->term); s->term = NULL; s->ptyfd = -1; s->ttyfd = -1; @@ -1608,151 +1597,109 @@ return 0; } debug("session_pty_req: session %d alloc %s", s->self, s->tty); + + /* for SSH1 the tty modes length is not given */ + if (!compat20) + n_bytes = packet_remaining(); + tty_parse_modes(s->ttyfd, &n_bytes); + /* * Add a cleanup function to clear the utmp entry and record logout * time in case we call fatal() (e.g., the connection gets closed). */ - fatal_add_cleanup(pty_cleanup_proc, (void *)s); - pty_setowner(s->pw, s->tty); - /* Get window size from the packet. */ - pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); + fatal_add_cleanup(session_pty_cleanup, (void *)s); + if (!use_privsep) + pty_setowner(s->pw, s->tty); - /* Get tty modes from the packet. */ - tty_parse_modes(s->ttyfd, &n_bytes); - packet_done(); + /* Set window size from the packet. */ + pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); + packet_check_eom(); session_proctitle(s); - return 1; } -int +static int session_subsystem_req(Session *s) { + struct stat st; u_int len; int success = 0; - char *subsys = packet_get_string(&len); + char *cmd, *subsys = packet_get_string(&len); int i; - packet_done(); - log("subsystem request for %s", subsys); + packet_check_eom(); + log("subsystem request for %.100s", subsys); for (i = 0; i < options.num_subsystems; i++) { - if(strcmp(subsys, options.subsystem_name[i]) == 0) { - debug("subsystem: exec() %s", options.subsystem_command[i]); + if (strcmp(subsys, options.subsystem_name[i]) == 0) { + cmd = options.subsystem_command[i]; + if (stat(cmd, &st) < 0) { + error("subsystem: cannot stat %s: %s", cmd, + strerror(errno)); + break; + } + debug("subsystem: exec() %s", cmd); s->is_subsystem = 1; - do_exec_no_pty(s, options.subsystem_command[i]); + do_exec(s, cmd); success = 1; + break; } } if (!success) - log("subsystem request for %s failed, subsystem not found", subsys); + log("subsystem request for %.100s failed, subsystem not found", + subsys); xfree(subsys); return success; } -int +static int session_x11_req(Session *s) { - int fd; - struct stat st; - if (no_x11_forwarding_flag) { - debug("X11 forwarding disabled in user configuration file."); - return 0; - } - if (!options.x11_forwarding) { - debug("X11 forwarding disabled in server configuration file."); - return 0; - } - if (!options.xauth_location || - (stat(options.xauth_location, &st) == -1)) { - packet_send_debug("No xauth program; cannot forward with spoofing."); - return 0; - } - if (xauthfile != NULL) { - debug("X11 fwd already started."); - return 0; - } - - debug("Received request for X11 forwarding with auth spoofing."); - if (s->display != NULL) - packet_disconnect("Protocol error: X11 display already set."); + int success; s->single_connection = packet_get_char(); s->auth_proto = packet_get_string(NULL); s->auth_data = packet_get_string(NULL); s->screen = packet_get_int(); - packet_done(); + packet_check_eom(); - s->display = x11_create_display_inet(s->screen, options.x11_display_offset); - if (s->display == NULL) { - xfree(s->auth_proto); - xfree(s->auth_data); - return 0; - } - xauthfile = xmalloc(MAXPATHLEN); - strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); - temporarily_use_uid(s->pw); - if (mkdtemp(xauthfile) == NULL) { - restore_uid(); - error("private X11 dir: mkdtemp %s failed: %s", - xauthfile, strerror(errno)); - xfree(xauthfile); - xauthfile = NULL; + success = session_setup_x11fwd(s); + if (!success) { xfree(s->auth_proto); xfree(s->auth_data); - /* XXXX remove listening channels */ - return 0; + s->auth_proto = NULL; + s->auth_data = NULL; } - strlcat(xauthfile, "/cookies", MAXPATHLEN); - fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); - if (fd >= 0) - close(fd); - restore_uid(); - fatal_add_cleanup(xauthfile_cleanup_proc, s->pw); - return 1; + return success; } -int +static int session_shell_req(Session *s) { - /* if forced_command == NULL, the shell is execed */ - char *shell = forced_command; - packet_done(); - if (s->ttyfd == -1) - do_exec_no_pty(s, shell); - else - do_exec_pty(s, shell); + packet_check_eom(); + do_exec(s, NULL); return 1; } -int +static int session_exec_req(Session *s) { u_int len; char *command = packet_get_string(&len); - packet_done(); - if (forced_command) { - original_command = command; - command = forced_command; - debug("Forced command '%.500s'", forced_command); - } - if (s->ttyfd == -1) - do_exec_no_pty(s, command); - else - do_exec_pty(s, command); - if (forced_command == NULL) - xfree(command); + packet_check_eom(); + do_exec(s, command); + xfree(command); return 1; } -int +static int session_auth_agent_req(Session *s) { static int called = 0; - packet_done(); + packet_check_eom(); if (no_agent_forwarding_flag) { debug("session_auth_agent_req: no_agent_forwarding_flag"); return 0; @@ -1765,28 +1712,18 @@ } } -void -session_input_channel_req(int id, void *arg) +int +session_input_channel_req(Channel *c, const char *rtype) { - u_int len; - int reply; int success = 0; - char *rtype; Session *s; - Channel *c; - rtype = packet_get_string(&len); - reply = packet_get_char(); - - s = session_by_channel(id); - if (s == NULL) - fatal("session_input_channel_req: channel %d: no session", id); - c = channel_lookup(id); - if (c == NULL) - fatal("session_input_channel_req: channel %d: bad channel", id); - - debug("session_input_channel_req: session %d channel %d request %s reply %d", - s->self, id, rtype, reply); + if ((s = session_by_channel(c->self)) == NULL) { + log("session_input_channel_req: no session %d req %.100s", + c->self, rtype); + return 0; + } + debug("session_input_channel_req: session %d req %s", s->self, rtype); /* * a session is in LARVAL state until a shell, a command @@ -1810,14 +1747,7 @@ if (strcmp(rtype, "window-change") == 0) { success = session_window_change_req(s); } - - if (reply) { - packet_start(success ? - SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(c->remote_id); - packet_send(); - } - xfree(rtype); + return success; } void @@ -1834,25 +1764,35 @@ channel_set_fds(s->chanid, fdout, fdin, fderr, fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1); + 1, + CHAN_SES_WINDOW_DEFAULT); } +/* + * Function to perform pty cleanup. Also called if we get aborted abnormally + * (e.g., due to a dropped connection). + */ void -session_pty_cleanup(Session *s) +session_pty_cleanup2(void *session) { - if (s == NULL || s->ttyfd == -1) + Session *s = session; + + if (s == NULL) { + error("session_pty_cleanup: no session"); + return; + } + if (s->ttyfd == -1) return; debug("session_pty_cleanup: session %d release %s", s->self, s->tty); - /* Cancel the cleanup function. */ - fatal_remove_cleanup(pty_cleanup_proc, (void *)s); - /* Record that the user has logged out. */ - record_logout(s->pid, s->tty); + if (s->pid != 0) + record_logout(s->pid, s->tty, s->pw->pw_name); /* Release the pseudo-tty. */ - pty_release(s->tty); + if (getuid() == 0) + pty_release(s->tty); /* * Close the server side of the socket pairs. We must do this after @@ -1860,32 +1800,41 @@ * while we're still cleaning up. */ if (close(s->ptymaster) < 0) - error("close(s->ptymaster): %s", strerror(errno)); + error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); + + /* unlink pty from session */ + s->ttyfd = -1; } void +session_pty_cleanup(void *session) +{ + PRIVSEP(session_pty_cleanup2(session)); +} + +static void session_exit_message(Session *s, int status) { Channel *c; - if (s == NULL) - fatal("session_close: no session"); - c = channel_lookup(s->chanid); - if (c == NULL) - fatal("session_close: session %d: no channel %d", + + if ((c = channel_lookup(s->chanid)) == NULL) + fatal("session_exit_message: session %d: no channel %d", s->self, s->chanid); - debug("session_exit_message: session %d channel %d pid %d", - s->self, s->chanid, s->pid); + debug("session_exit_message: session %d channel %d pid %ld", + s->self, s->chanid, (long)s->pid); if (WIFEXITED(status)) { - channel_request_start(s->chanid, - "exit-status", 0); + channel_request_start(s->chanid, "exit-status", 0); packet_put_int(WEXITSTATUS(status)); packet_send(); } else if (WIFSIGNALED(status)) { - channel_request_start(s->chanid, - "exit-signal", 0); + channel_request_start(s->chanid, "exit-signal", 0); packet_put_int(WTERMSIG(status)); +#ifdef WCOREDUMP packet_put_char(WCOREDUMP(status)); +#else /* WCOREDUMP */ + packet_put_char(0); +#endif /* WCOREDUMP */ packet_put_cstring(""); packet_put_cstring(""); packet_send(); @@ -1909,25 +1858,24 @@ } void -session_free(Session *s) +session_close(Session *s) { - debug("session_free: session %d pid %d", s->self, s->pid); + debug("session_close: session %d pid %ld", s->self, (long)s->pid); + if (s->ttyfd != -1) { + fatal_remove_cleanup(session_pty_cleanup, (void *)s); + session_pty_cleanup(s); + } if (s->term) xfree(s->term); if (s->display) xfree(s->display); + if (s->auth_display) + xfree(s->auth_display); if (s->auth_data) xfree(s->auth_data); if (s->auth_proto) xfree(s->auth_proto); s->used = 0; -} - -void -session_close(Session *s) -{ - session_pty_cleanup(s); - session_free(s); session_proctitle(s); } @@ -1936,7 +1884,8 @@ { Session *s = session_by_pid(pid); if (s == NULL) { - debug("session_close_by_pid: no session for pid %d", s->pid); + debug("session_close_by_pid: no session for pid %ld", + (long)pid); return; } if (s->chanid != -1) @@ -1953,34 +1902,51 @@ { Session *s = session_by_channel(id); if (s == NULL) { - debug("session_close_by_channel: no session for channel %d", id); + debug("session_close_by_channel: no session for id %d", id); return; } - /* disconnect channel */ + debug("session_close_by_channel: channel %d child %ld", + id, (long)s->pid); + if (s->pid != 0) { + debug("session_close_by_channel: channel %d: has child", id); + /* + * delay detach of session, but release pty, since + * the fd's to the child are already closed + */ + if (s->ttyfd != -1) { + fatal_remove_cleanup(session_pty_cleanup, (void *)s); + session_pty_cleanup(s); + } + return; + } + /* detach by removing callback */ channel_cancel_cleanup(s->chanid); s->chanid = -1; + session_close(s); +} - debug("session_close_by_channel: channel %d kill %d", id, s->pid); - if (s->pid == 0) { - /* close session immediately */ - session_close(s); - } else { - /* notify child, delay session cleanup */ - if (s->pid <= 1) - fatal("session_close_by_channel: Unsafe s->pid = %d", s->pid); - if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0) - error("session_close_by_channel: kill %d: %s", - s->pid, strerror(errno)); +void +session_destroy_all(void (*closefunc)(Session *)) +{ + int i; + for (i = 0; i < MAX_SESSIONS; i++) { + Session *s = &sessions[i]; + if (s->used) { + if (closefunc != NULL) + closefunc(s); + else + session_close(s); + } } } -char * +static char * session_tty_list(void) { static char buf[1024]; int i; buf[0] = '\0'; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1) { if (buf[0] != '\0') @@ -2002,9 +1968,84 @@ setproctitle("%s@%s", s->pw->pw_name, session_tty_list()); } -void -do_authenticated2(Authctxt *authctxt) +int +session_setup_x11fwd(Session *s) { + struct stat st; + char display[512], auth_display[512]; + char hostname[MAXHOSTNAMELEN]; + + if (no_x11_forwarding_flag) { + packet_send_debug("X11 forwarding disabled in user configuration file."); + return 0; + } + if (!options.x11_forwarding) { + debug("X11 forwarding disabled in server configuration file."); + return 0; + } + if (!options.xauth_location || + (stat(options.xauth_location, &st) == -1)) { + packet_send_debug("No xauth program; cannot forward with spoofing."); + return 0; + } + if (options.use_login) { + packet_send_debug("X11 forwarding disabled; " + "not compatible with UseLogin=yes."); + return 0; + } + if (s->display != NULL) { + debug("X11 display already set."); + return 0; + } + if (x11_create_display_inet(options.x11_display_offset, + options.x11_use_localhost, s->single_connection, + &s->display_number) == -1) { + debug("x11_create_display_inet failed."); + return 0; + } + + /* Set up a suitable value for the DISPLAY variable. */ + if (gethostname(hostname, sizeof(hostname)) < 0) + fatal("gethostname: %.100s", strerror(errno)); + /* + * auth_display must be used as the displayname when the + * authorization entry is added with xauth(1). This will be + * different than the DISPLAY string for localhost displays. + */ + if (options.x11_use_localhost) { + snprintf(display, sizeof display, "localhost:%u.%u", + s->display_number, s->screen); + snprintf(auth_display, sizeof auth_display, "unix:%u.%u", + s->display_number, s->screen); + s->display = xstrdup(display); + s->auth_display = xstrdup(auth_display); + } else { +#ifdef IPADDR_IN_DISPLAY + struct hostent *he; + struct in_addr my_addr; + + he = gethostbyname(hostname); + if (he == NULL) { + error("Can't get IP address for X11 DISPLAY."); + packet_send_debug("Can't get IP address for X11 DISPLAY."); + return 0; + } + memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr)); + snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr), + s->display_number, s->screen); +#else + snprintf(display, sizeof display, "%.400s:%u.%u", hostname, + s->display_number, s->screen); +#endif + s->display = xstrdup(display); + s->auth_display = xstrdup(display); + } + + return 1; +} - server_loop2(); +static void +do_authenticated2(Authctxt *authctxt) +{ + server_loop2(authctxt); } Index: src/crypto/openssh/session.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/session.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 session.h --- src/crypto/openssh/session.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/session.h 30 Jun 2002 11:38:00 -0000 @@ -1,7 +1,8 @@ -/* $OpenBSD: session.h,v 1.6 2001/03/21 11:43:45 markus Exp $ */ +/* $OpenBSD: session.h,v 1.18 2002/06/23 21:06:41 deraadt Exp $ */ +/* $FreeBSD: src/crypto/openssh/session.h,v 1.4 2002/06/29 11:48:58 des Exp $ */ /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,11 +27,46 @@ #ifndef SESSION_H #define SESSION_H -void do_authenticated(Authctxt *ac); +#define TTYSZ 64 +typedef struct Session Session; +struct Session { + int used; + int self; + struct passwd *pw; + Authctxt *authctxt; + pid_t pid; + /* tty */ + char *term; + int ptyfd, ttyfd, ptymaster; + u_int row, col, xpixel, ypixel; + char tty[TTYSZ]; + /* last login */ + char hostname[MAXHOSTNAMELEN]; + time_t last_login_time; + /* X11 */ + u_int display_number; + char *display; + u_int screen; + char *auth_display; + char *auth_proto; + char *auth_data; + int single_connection; + /* proto 2 */ + int chanid; + int is_subsystem; +}; -int session_open(int id); -void session_input_channel_req(int id, void *arg); -void session_close_by_pid(pid_t pid, int status); -void session_close_by_channel(int id, void *arg); +void do_authenticated(Authctxt *); +int session_open(Authctxt*, int); +int session_input_channel_req(Channel *, const char *); +void session_close_by_pid(pid_t, int); +void session_close_by_channel(int, void *); +void session_destroy_all(void (*)(Session *)); +void session_pty_cleanup2(void *); + +Session *session_new(void); +Session *session_by_tty(char *); +void session_close(Session *); +void do_setusercontext(struct passwd *); #endif Index: src/crypto/openssh/sftp-client.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-client.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-client.c --- src/crypto/openssh/sftp-client.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-client.c 30 Jun 2002 11:38:00 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,34 +24,38 @@ /* XXX: memleaks */ /* XXX: signed vs unsigned */ -/* XXX: redesign to allow concurrent overlapped operations */ -/* XXX: we use fatal too much, error may be more appropriate in places */ +/* XXX: remove all logging, only return status codes */ /* XXX: copy between two remote sites */ #include "includes.h" -RCSID("$OpenBSD: sftp-client.c,v 1.16 2001/04/05 10:42:52 markus Exp $"); +RCSID("$OpenBSD: sftp-client.c,v 1.33 2002/06/23 09:30:14 deraadt Exp $"); + +#include "openbsd-compat/fake-queue.h" -#include "ssh.h" #include "buffer.h" #include "bufaux.h" #include "getput.h" #include "xmalloc.h" #include "log.h" #include "atomicio.h" -#include "pathnames.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" -/* How much data to read/write at at time during copies */ -/* XXX: what should this be? */ -#define COPY_SIZE 8192 +/* Minimum amount of data to read at at time */ +#define MIN_READ_SIZE 512 -/* Message ID */ -static u_int msg_id = 1; +struct sftp_conn { + int fd_in; + int fd_out; + u_int transfer_buflen; + u_int num_requests; + u_int version; + u_int msg_id; +}; -void +static void send_msg(int fd, Buffer *m) { int mlen = buffer_len(m); @@ -70,7 +74,7 @@ buffer_free(&oqueue); } -void +static void get_msg(int fd, Buffer *m) { u_int len, msg_len; @@ -84,7 +88,7 @@ msg_len = GET_32BIT(buf); if (msg_len > 256 * 1024) - fatal("Received message too long %d", msg_len); + fatal("Received message too long %u", msg_len); while (msg_len) { len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf))); @@ -98,7 +102,7 @@ } } -void +static void send_string_request(int fd, u_int id, u_int code, char *s, u_int len) { @@ -109,11 +113,11 @@ buffer_put_int(&msg, id); buffer_put_string(&msg, s, len); send_msg(fd, &msg); - debug3("Sent message fd %d T:%d I:%d", fd, code, id); + debug3("Sent message fd %d T:%u I:%u", fd, code, id); buffer_free(&msg); } -void +static void send_string_attrs_request(int fd, u_int id, u_int code, char *s, u_int len, Attrib *a) { @@ -125,12 +129,12 @@ buffer_put_string(&msg, s, len); encode_attrib(&msg, a); send_msg(fd, &msg); - debug3("Sent message fd %d T:%d I:%d", fd, code, id); + debug3("Sent message fd %d T:%u I:%u", fd, code, id); buffer_free(&msg); } -u_int -get_status(int fd, int expected_id) +static u_int +get_status(int fd, u_int expected_id) { Buffer msg; u_int type, id, status; @@ -141,20 +145,20 @@ id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); + fatal("ID mismatch (%u != %u)", id, expected_id); if (type != SSH2_FXP_STATUS) - fatal("Expected SSH2_FXP_STATUS(%d) packet, got %d", + fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", SSH2_FXP_STATUS, type); status = buffer_get_int(&msg); buffer_free(&msg); - debug3("SSH2_FXP_STATUS %d", status); + debug3("SSH2_FXP_STATUS %u", status); return(status); } -char * +static char * get_handle(int fd, u_int expected_id, u_int *len) { Buffer msg; @@ -167,14 +171,14 @@ id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); + fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { int status = buffer_get_int(&msg); error("Couldn't get handle: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_HANDLE) - fatal("Expected SSH2_FXP_HANDLE(%d) packet, got %d", + fatal("Expected SSH2_FXP_HANDLE(%u) packet, got %u", SSH2_FXP_HANDLE, type); handle = buffer_get_string(&msg, len); @@ -183,7 +187,7 @@ return(handle); } -Attrib * +static Attrib * get_decode_stat(int fd, u_int expected_id, int quiet) { Buffer msg; @@ -196,9 +200,9 @@ type = buffer_get_char(&msg); id = buffer_get_int(&msg); - debug3("Received stat reply T:%d I:%d", type, id); + debug3("Received stat reply T:%u I:%u", type, id); if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); + fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { int status = buffer_get_int(&msg); @@ -208,7 +212,7 @@ error("Couldn't stat remote file: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_ATTRS) { - fatal("Expected SSH2_FXP_ATTRS(%d) packet, got %d", + fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", SSH2_FXP_ATTRS, type); } a = decode_attrib(&msg); @@ -217,11 +221,13 @@ return(a); } -int -do_init(int fd_in, int fd_out) +struct sftp_conn * +do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) { - int type, version; + u_int type; + int version; Buffer msg; + struct sftp_conn *ret; buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_INIT); @@ -234,10 +240,10 @@ /* Expecting a VERSION reply */ if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { - error("Invalid packet back from SSH2_FXP_INIT (type %d)", + error("Invalid packet back from SSH2_FXP_INIT (type %u)", type); buffer_free(&msg); - return(-1); + return(NULL); } version = buffer_get_int(&msg); @@ -255,25 +261,43 @@ buffer_free(&msg); - return(version); + ret = xmalloc(sizeof(*ret)); + ret->fd_in = fd_in; + ret->fd_out = fd_out; + ret->transfer_buflen = transfer_buflen; + ret->num_requests = num_requests; + ret->version = version; + ret->msg_id = 1; + + /* Some filexfer v.0 servers don't support large packets */ + if (version == 0) + ret->transfer_buflen = MIN(ret->transfer_buflen, 20480); + + return(ret); +} + +u_int +sftp_proto_version(struct sftp_conn *conn) +{ + return(conn->version); } int -do_close(int fd_in, int fd_out, char *handle, u_int handle_len) +do_close(struct sftp_conn *conn, char *handle, u_int handle_len) { u_int id, status; Buffer msg; buffer_init(&msg); - id = msg_id++; + id = conn->msg_id++; buffer_put_char(&msg, SSH2_FXP_CLOSE); buffer_put_int(&msg, id); buffer_put_string(&msg, handle, handle_len); - send_msg(fd_out, &msg); - debug3("Sent message SSH2_FXP_CLOSE I:%d", id); + send_msg(conn->fd_out, &msg); + debug3("Sent message SSH2_FXP_CLOSE I:%u", id); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) error("Couldn't close file: %s", fx2txt(status)); @@ -283,25 +307,25 @@ } -int -do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, +static int +do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, SFTP_DIRENT ***dir) { Buffer msg; u_int type, id, handle_len, i, expected_id, ents = 0; char *handle; - id = msg_id++; + id = conn->msg_id++; buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_OPENDIR); buffer_put_int(&msg, id); buffer_put_cstring(&msg, path); - send_msg(fd_out, &msg); + send_msg(conn->fd_out, &msg); buffer_clear(&msg); - handle = get_handle(fd_in, id, &handle_len); + handle = get_handle(conn->fd_in, id, &handle_len); if (handle == NULL) return(-1); @@ -310,32 +334,31 @@ *dir = xmalloc(sizeof(**dir)); (*dir)[0] = NULL; } - - for(;;) { + for (;;) { int count; - id = expected_id = msg_id++; + id = expected_id = conn->msg_id++; - debug3("Sending SSH2_FXP_READDIR I:%d", id); + debug3("Sending SSH2_FXP_READDIR I:%u", id); buffer_clear(&msg); buffer_put_char(&msg, SSH2_FXP_READDIR); buffer_put_int(&msg, id); buffer_put_string(&msg, handle, handle_len); - send_msg(fd_out, &msg); + send_msg(conn->fd_out, &msg); buffer_clear(&msg); - get_msg(fd_in, &msg); + get_msg(conn->fd_in, &msg); type = buffer_get_char(&msg); id = buffer_get_int(&msg); - debug3("Received reply T:%d I:%d", type, id); + debug3("Received reply T:%u I:%u", type, id); if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); + fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { int status = buffer_get_int(&msg); @@ -347,18 +370,18 @@ } else { error("Couldn't read directory: %s", fx2txt(status)); - do_close(fd_in, fd_out, handle, handle_len); + do_close(conn, handle, handle_len); return(status); } } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); count = buffer_get_int(&msg); if (count == 0) break; debug3("Received %d SSH2_FXP_NAME responses", count); - for(i = 0; i < count; i++) { + for (i = 0; i < count; i++) { char *filename, *longname; Attrib *a; @@ -385,29 +408,29 @@ } buffer_free(&msg); - do_close(fd_in, fd_out, handle, handle_len); + do_close(conn, handle, handle_len); xfree(handle); return(0); } int -do_ls(int fd_in, int fd_out, char *path) +do_ls(struct sftp_conn *conn, char *path) { - return(do_lsreaddir(fd_in, fd_out, path, 1, NULL)); + return(do_lsreaddir(conn, path, 1, NULL)); } int -do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir) +do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) { - return(do_lsreaddir(fd_in, fd_out, path, 0, dir)); + return(do_lsreaddir(conn, path, 0, dir)); } void free_sftp_dirents(SFTP_DIRENT **s) { int i; - - for(i = 0; s[i]; i++) { + + for (i = 0; s[i]; i++) { xfree(s[i]->filename); xfree(s[i]->longname); xfree(s[i]); @@ -416,30 +439,31 @@ } int -do_rm(int fd_in, int fd_out, char *path) +do_rm(struct sftp_conn *conn, char *path) { u_int status, id; debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); - id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_REMOVE, path, strlen(path)); - status = get_status(fd_in, id); + id = conn->msg_id++; + send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, + strlen(path)); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) error("Couldn't delete file: %s", fx2txt(status)); return(status); } int -do_mkdir(int fd_in, int fd_out, char *path, Attrib *a) +do_mkdir(struct sftp_conn *conn, char *path, Attrib *a) { u_int status, id; - id = msg_id++; - send_string_attrs_request(fd_out, id, SSH2_FXP_MKDIR, path, + id = conn->msg_id++; + send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path, strlen(path), a); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) error("Couldn't create directory: %s", fx2txt(status)); @@ -447,14 +471,15 @@ } int -do_rmdir(int fd_in, int fd_out, char *path) +do_rmdir(struct sftp_conn *conn, char *path) { u_int status, id; - id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_RMDIR, path, strlen(path)); + id = conn->msg_id++; + send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path, + strlen(path)); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) error("Couldn't remove directory: %s", fx2txt(status)); @@ -462,45 +487,61 @@ } Attrib * -do_stat(int fd_in, int fd_out, char *path, int quiet) +do_stat(struct sftp_conn *conn, char *path, int quiet) { u_int id; - id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path)); - return(get_decode_stat(fd_in, id, quiet)); + id = conn->msg_id++; + + send_string_request(conn->fd_out, id, + conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, + path, strlen(path)); + + return(get_decode_stat(conn->fd_in, id, quiet)); } Attrib * -do_lstat(int fd_in, int fd_out, char *path, int quiet) +do_lstat(struct sftp_conn *conn, char *path, int quiet) { u_int id; - id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path)); - return(get_decode_stat(fd_in, id, quiet)); + if (conn->version == 0) { + if (quiet) + debug("Server version does not support lstat operation"); + else + log("Server version does not support lstat operation"); + return(do_stat(conn, path, quiet)); + } + + id = conn->msg_id++; + send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path, + strlen(path)); + + return(get_decode_stat(conn->fd_in, id, quiet)); } Attrib * -do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet) +do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) { u_int id; - id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len); - return(get_decode_stat(fd_in, id, quiet)); + id = conn->msg_id++; + send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle, + handle_len); + + return(get_decode_stat(conn->fd_in, id, quiet)); } int -do_setstat(int fd_in, int fd_out, char *path, Attrib *a) +do_setstat(struct sftp_conn *conn, char *path, Attrib *a) { u_int status, id; - id = msg_id++; - send_string_attrs_request(fd_out, id, SSH2_FXP_SETSTAT, path, + id = conn->msg_id++; + send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path, strlen(path), a); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) error("Couldn't setstat on \"%s\": %s", path, fx2txt(status)); @@ -509,16 +550,16 @@ } int -do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len, +do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, Attrib *a) { u_int status, id; - id = msg_id++; - send_string_attrs_request(fd_out, id, SSH2_FXP_FSETSTAT, handle, + id = conn->msg_id++; + send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle, handle_len, a); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) error("Couldn't fsetstat: %s", fx2txt(status)); @@ -526,24 +567,25 @@ } char * -do_realpath(int fd_in, int fd_out, char *path) +do_realpath(struct sftp_conn *conn, char *path) { Buffer msg; u_int type, expected_id, count, id; char *filename, *longname; Attrib *a; - expected_id = id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path)); + expected_id = id = conn->msg_id++; + send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path, + strlen(path)); buffer_init(&msg); - get_msg(fd_in, &msg); + get_msg(conn->fd_in, &msg); type = buffer_get_char(&msg); id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); + fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status = buffer_get_int(&msg); @@ -551,7 +593,7 @@ error("Couldn't canonicalise: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); count = buffer_get_int(&msg); @@ -572,7 +614,7 @@ } int -do_rename(int fd_in, int fd_out, char *oldpath, char *newpath) +do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) { Buffer msg; u_int status, id; @@ -580,70 +622,76 @@ buffer_init(&msg); /* Send rename request */ - id = msg_id++; + id = conn->msg_id++; buffer_put_char(&msg, SSH2_FXP_RENAME); buffer_put_int(&msg, id); buffer_put_cstring(&msg, oldpath); buffer_put_cstring(&msg, newpath); - send_msg(fd_out, &msg); + send_msg(conn->fd_out, &msg); debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath, newpath); buffer_free(&msg); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) - error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, - fx2txt(status)); + error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, + newpath, fx2txt(status)); return(status); } int -do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath) +do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) { Buffer msg; u_int status, id; + if (conn->version < 3) { + error("This server does not support the symlink operation"); + return(SSH2_FX_OP_UNSUPPORTED); + } + buffer_init(&msg); /* Send rename request */ - id = msg_id++; + id = conn->msg_id++; buffer_put_char(&msg, SSH2_FXP_SYMLINK); buffer_put_int(&msg, id); buffer_put_cstring(&msg, oldpath); buffer_put_cstring(&msg, newpath); - send_msg(fd_out, &msg); + send_msg(conn->fd_out, &msg); debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, newpath); buffer_free(&msg); - status = get_status(fd_in, id); + status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) - error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, - fx2txt(status)); + error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, + newpath, fx2txt(status)); return(status); } char * -do_readlink(int fd_in, int fd_out, char *path) +do_readlink(struct sftp_conn *conn, char *path) { Buffer msg; u_int type, expected_id, count, id; char *filename, *longname; Attrib *a; - expected_id = id = msg_id++; - send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path)); + expected_id = id = conn->msg_id++; + send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path, + strlen(path)); buffer_init(&msg); - get_msg(fd_in, &msg); + get_msg(conn->fd_in, &msg); type = buffer_get_char(&msg); id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); + fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status = buffer_get_int(&msg); @@ -651,7 +699,7 @@ error("Couldn't readlink: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); count = buffer_get_int(&msg); @@ -671,19 +719,46 @@ return(filename); } +static void +send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, + char *handle, u_int handle_len) +{ + Buffer msg; + + buffer_init(&msg); + buffer_clear(&msg); + buffer_put_char(&msg, SSH2_FXP_READ); + buffer_put_int(&msg, id); + buffer_put_string(&msg, handle, handle_len); + buffer_put_int64(&msg, offset); + buffer_put_int(&msg, len); + send_msg(fd_out, &msg); + buffer_free(&msg); +} + int -do_download(int fd_in, int fd_out, char *remote_path, char *local_path, +do_download(struct sftp_conn *conn, char *remote_path, char *local_path, int pflag) { - int local_fd; - u_int expected_id, handle_len, mode, type, id; - u_int64_t offset; - char *handle; - Buffer msg; Attrib junk, *a; - int status; + Buffer msg; + char *handle; + int local_fd, status, num_req, max_req, write_error; + int read_error, write_errno; + u_int64_t offset, size; + u_int handle_len, mode, type, id, buflen; + struct request { + u_int id; + u_int len; + u_int64_t offset; + TAILQ_ENTRY(request) tq; + }; + TAILQ_HEAD(reqhead, request) requests; + struct request *req; + + TAILQ_INIT(&requests); - a = do_stat(fd_in, fd_out, remote_path, 0); + a = do_stat(conn, remote_path, 0); if (a == NULL) return(-1); @@ -699,130 +774,209 @@ return(-1); } - local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); - if (local_fd == -1) { - error("Couldn't open local file \"%s\" for writing: %s", - local_path, strerror(errno)); - return(-1); - } + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) + size = a->size; + else + size = 0; + buflen = conn->transfer_buflen; buffer_init(&msg); /* Send open request */ - id = msg_id++; + id = conn->msg_id++; buffer_put_char(&msg, SSH2_FXP_OPEN); buffer_put_int(&msg, id); buffer_put_cstring(&msg, remote_path); buffer_put_int(&msg, SSH2_FXF_READ); attrib_clear(&junk); /* Send empty attributes */ encode_attrib(&msg, &junk); - send_msg(fd_out, &msg); - debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); + send_msg(conn->fd_out, &msg); + debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); - handle = get_handle(fd_in, id, &handle_len); + handle = get_handle(conn->fd_in, id, &handle_len); if (handle == NULL) { buffer_free(&msg); - close(local_fd); + return(-1); + } + + local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); + if (local_fd == -1) { + error("Couldn't open local file \"%s\" for writing: %s", + local_path, strerror(errno)); + buffer_free(&msg); + xfree(handle); return(-1); } /* Read from remote and write to local */ - offset = 0; - for(;;) { - u_int len; + write_error = read_error = write_errno = num_req = offset = 0; + max_req = 1; + while (num_req > 0 || max_req > 0) { char *data; + u_int len; - id = expected_id = msg_id++; - - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_READ); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - buffer_put_int64(&msg, offset); - buffer_put_int(&msg, COPY_SIZE); - send_msg(fd_out, &msg); - debug3("Sent message SSH2_FXP_READ I:%d O:%llu S:%u", - id, (unsigned long long)offset, COPY_SIZE); + /* Send some more requests */ + while (num_req < max_req) { + debug3("Request range %llu -> %llu (%d/%d)", + (unsigned long long)offset, + (unsigned long long)offset + buflen - 1, + num_req, max_req); + req = xmalloc(sizeof(*req)); + req->id = conn->msg_id++; + req->len = buflen; + req->offset = offset; + offset += buflen; + num_req++; + TAILQ_INSERT_TAIL(&requests, req, tq); + send_read_request(conn->fd_out, req->id, req->offset, + req->len, handle, handle_len); + } buffer_clear(&msg); - - get_msg(fd_in, &msg); + get_msg(conn->fd_in, &msg); type = buffer_get_char(&msg); id = buffer_get_int(&msg); - debug3("Received reply T:%d I:%d", type, id); - if (id != expected_id) - fatal("ID mismatch (%d != %d)", id, expected_id); - if (type == SSH2_FXP_STATUS) { + debug3("Received reply T:%u I:%u R:%d", type, id, max_req); + + /* Find the request in our queue */ + for(req = TAILQ_FIRST(&requests); + req != NULL && req->id != id; + req = TAILQ_NEXT(req, tq)) + ; + if (req == NULL) + fatal("Unexpected reply %u", id); + + switch (type) { + case SSH2_FXP_STATUS: status = buffer_get_int(&msg); + if (status != SSH2_FX_EOF) + read_error = 1; + max_req = 0; + TAILQ_REMOVE(&requests, req, tq); + xfree(req); + num_req--; + break; + case SSH2_FXP_DATA: + data = buffer_get_string(&msg, &len); + debug3("Received data %llu -> %llu", + (unsigned long long)req->offset, + (unsigned long long)req->offset + len - 1); + if (len > req->len) + fatal("Received more data than asked for " + "%u > %u", len, req->len); + if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || + atomicio(write, local_fd, data, len) != len) && + !write_error) { + write_errno = errno; + write_error = 1; + max_req = 0; + } + xfree(data); - if (status == SSH2_FX_EOF) - break; - else { - error("Couldn't read from remote " - "file \"%s\" : %s", remote_path, - fx2txt(status)); - do_close(fd_in, fd_out, handle, handle_len); - goto done; + if (len == req->len) { + TAILQ_REMOVE(&requests, req, tq); + xfree(req); + num_req--; + } else { + /* Resend the request for the missing data */ + debug3("Short data block, re-requesting " + "%llu -> %llu (%2d)", + (unsigned long long)req->offset + len, + (unsigned long long)req->offset + + req->len - 1, num_req); + req->id = conn->msg_id++; + req->len -= len; + req->offset += len; + send_read_request(conn->fd_out, req->id, + req->offset, req->len, handle, handle_len); + /* Reduce the request size */ + if (len < buflen) + buflen = MAX(MIN_READ_SIZE, len); } - } else if (type != SSH2_FXP_DATA) { - fatal("Expected SSH2_FXP_DATA(%d) packet, got %d", + if (max_req > 0) { /* max_req = 0 iff EOF received */ + if (size > 0 && offset > size) { + /* Only one request at a time + * after the expected EOF */ + debug3("Finish at %llu (%2d)", + (unsigned long long)offset, + num_req); + max_req = 1; + } + else if (max_req < conn->num_requests + 1) { + ++max_req; + } + } + break; + default: + fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", SSH2_FXP_DATA, type); } - - data = buffer_get_string(&msg, &len); - if (len > COPY_SIZE) - fatal("Received more data than asked for %d > %d", - len, COPY_SIZE); - - debug3("In read loop, got %d offset %llu", len, - (unsigned long long)offset); - if (atomicio(write, local_fd, data, len) != len) { - error("Couldn't write to \"%s\": %s", local_path, - strerror(errno)); - do_close(fd_in, fd_out, handle, handle_len); - status = -1; - xfree(data); - goto done; - } - - offset += len; - xfree(data); } - status = do_close(fd_in, fd_out, handle, handle_len); - /* Override umask and utimes if asked */ - if (pflag && fchmod(local_fd, mode) == -1) - error("Couldn't set mode on \"%s\": %s", local_path, - strerror(errno)); - if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { - struct timeval tv[2]; - tv[0].tv_sec = a->atime; - tv[1].tv_sec = a->mtime; - tv[0].tv_usec = tv[1].tv_usec = 0; - if (utimes(local_path, tv) == -1) - error("Can't set times on \"%s\": %s", local_path, - strerror(errno)); + /* Sanity check */ + if (TAILQ_FIRST(&requests) != NULL) + fatal("Transfer complete, but requests still in queue"); + + if (read_error) { + error("Couldn't read from remote file \"%s\" : %s", + remote_path, fx2txt(status)); + do_close(conn, handle, handle_len); + } else if (write_error) { + error("Couldn't write to \"%s\": %s", local_path, + strerror(write_errno)); + status = -1; + do_close(conn, handle, handle_len); + } else { + status = do_close(conn, handle, handle_len); + + /* Override umask and utimes if asked */ +#ifdef HAVE_FCHMOD + if (pflag && fchmod(local_fd, mode) == -1) +#else + if (pflag && chmod(local_path, mode) == -1) +#endif /* HAVE_FCHMOD */ + error("Couldn't set mode on \"%s\": %s", local_path, + strerror(errno)); + if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { + struct timeval tv[2]; + tv[0].tv_sec = a->atime; + tv[1].tv_sec = a->mtime; + tv[0].tv_usec = tv[1].tv_usec = 0; + if (utimes(local_path, tv) == -1) + error("Can't set times on \"%s\": %s", + local_path, strerror(errno)); + } } - -done: close(local_fd); buffer_free(&msg); xfree(handle); - return status; + + return(status); } int -do_upload(int fd_in, int fd_out, char *local_path, char *remote_path, +do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, int pflag) { - int local_fd; - u_int handle_len, id; + int local_fd, status; + u_int handle_len, id, type; u_int64_t offset; - char *handle; + char *handle, *data; Buffer msg; struct stat sb; Attrib a; - int status; + u_int32_t startid; + u_int32_t ackid; + struct outstanding_ack { + u_int id; + u_int len; + u_int64_t offset; + TAILQ_ENTRY(outstanding_ack) tq; + }; + TAILQ_HEAD(ackhead, outstanding_ack) acks; + struct outstanding_ack *ack; + + TAILQ_INIT(&acks); if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { error("Couldn't open local file \"%s\" for reading: %s", @@ -846,85 +1000,123 @@ buffer_init(&msg); /* Send open request */ - id = msg_id++; + id = conn->msg_id++; buffer_put_char(&msg, SSH2_FXP_OPEN); buffer_put_int(&msg, id); buffer_put_cstring(&msg, remote_path); buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); encode_attrib(&msg, &a); - send_msg(fd_out, &msg); - debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); + send_msg(conn->fd_out, &msg); + debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); buffer_clear(&msg); - handle = get_handle(fd_in, id, &handle_len); + handle = get_handle(conn->fd_in, id, &handle_len); if (handle == NULL) { close(local_fd); buffer_free(&msg); return(-1); } + startid = ackid = id + 1; + data = xmalloc(conn->transfer_buflen); + /* Read from local and write to remote */ offset = 0; - for(;;) { + for (;;) { int len; - char data[COPY_SIZE]; /* * Can't use atomicio here because it returns 0 on EOF, thus losing * the last block of the file */ do - len = read(local_fd, data, COPY_SIZE); + len = read(local_fd, data, conn->transfer_buflen); while ((len == -1) && (errno == EINTR || errno == EAGAIN)); if (len == -1) fatal("Couldn't read from \"%s\": %s", local_path, strerror(errno)); - if (len == 0) + + if (len != 0) { + ack = xmalloc(sizeof(*ack)); + ack->id = ++id; + ack->offset = offset; + ack->len = len; + TAILQ_INSERT_TAIL(&acks, ack, tq); + + buffer_clear(&msg); + buffer_put_char(&msg, SSH2_FXP_WRITE); + buffer_put_int(&msg, ack->id); + buffer_put_string(&msg, handle, handle_len); + buffer_put_int64(&msg, offset); + buffer_put_string(&msg, data, len); + send_msg(conn->fd_out, &msg); + debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", + id, (unsigned long long)offset, len); + } else if (TAILQ_FIRST(&acks) == NULL) break; - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_WRITE); - buffer_put_int(&msg, ++id); - buffer_put_string(&msg, handle, handle_len); - buffer_put_int64(&msg, offset); - buffer_put_string(&msg, data, len); - send_msg(fd_out, &msg); - debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", - id, (unsigned long long)offset, len); - - status = get_status(fd_in, id); - if (status != SSH2_FX_OK) { - error("Couldn't write to remote file \"%s\": %s", - remote_path, fx2txt(status)); - do_close(fd_in, fd_out, handle, handle_len); - close(local_fd); - goto done; - } - debug3("In write loop, got %d offset %llu", len, - (unsigned long long)offset); + if (ack == NULL) + fatal("Unexpected ACK %u", id); + + if (id == startid || len == 0 || + id - ackid >= conn->num_requests) { + u_int r_id; + + buffer_clear(&msg); + get_msg(conn->fd_in, &msg); + type = buffer_get_char(&msg); + r_id = buffer_get_int(&msg); + + if (type != SSH2_FXP_STATUS) + fatal("Expected SSH2_FXP_STATUS(%d) packet, " + "got %d", SSH2_FXP_STATUS, type); + status = buffer_get_int(&msg); + debug3("SSH2_FXP_STATUS %d", status); + + /* Find the request in our queue */ + for(ack = TAILQ_FIRST(&acks); + ack != NULL && ack->id != r_id; + ack = TAILQ_NEXT(ack, tq)) + ; + if (ack == NULL) + fatal("Can't find request for ID %u", r_id); + TAILQ_REMOVE(&acks, ack, tq); + + if (status != SSH2_FX_OK) { + error("Couldn't write to remote file \"%s\": %s", + remote_path, fx2txt(status)); + do_close(conn, handle, handle_len); + close(local_fd); + goto done; + } + debug3("In write loop, ack for %u %u bytes at %llu", + ack->id, ack->len, (unsigned long long)ack->offset); + ++ackid; + free(ack); + } offset += len; } + xfree(data); if (close(local_fd) == -1) { error("Couldn't close local file \"%s\": %s", local_path, strerror(errno)); - do_close(fd_in, fd_out, handle, handle_len); + do_close(conn, handle, handle_len); status = -1; goto done; } /* Override umask and utimes if asked */ if (pflag) - do_fsetstat(fd_in, fd_out, handle, handle_len, &a); + do_fsetstat(conn, handle, handle_len, &a); - status = do_close(fd_in, fd_out, handle, handle_len); + status = do_close(conn, handle, handle_len); done: xfree(handle); buffer_free(&msg); - return status; + return(status); } - Index: src/crypto/openssh/sftp-client.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-client.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-client.h --- src/crypto/openssh/sftp-client.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-client.h 30 Jun 2002 11:38:00 -0000 @@ -1,7 +1,7 @@ -/* $OpenBSD: sftp-client.h,v 1.5 2001/04/05 10:42:52 markus Exp $ */ +/* $OpenBSD: sftp-client.h,v 1.10 2002/06/23 09:30:14 deraadt Exp $ */ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +26,9 @@ /* Client side of SSH2 filexfer protocol */ +#ifndef _SFTP_CLIENT_H +#define _SFTP_CLIENT_H + typedef struct SFTP_DIRENT SFTP_DIRENT; struct SFTP_DIRENT { @@ -38,57 +41,57 @@ * Initialiase a SSH filexfer connection. Returns -1 on error or * protocol version on success. */ -int do_init(int fd_in, int fd_out); +struct sftp_conn *do_init(int, int, u_int, u_int); + +u_int sftp_proto_version(struct sftp_conn *); /* Close file referred to by 'handle' */ -int do_close(int fd_in, int fd_out, char *handle, u_int handle_len); +int do_close(struct sftp_conn *, char *, u_int); /* List contents of directory 'path' to stdout */ -int do_ls(int fd_in, int fd_out, char *path); +int do_ls(struct sftp_conn *, char *); /* Read contents of 'path' to NULL-terminated array 'dir' */ -int do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir); +int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ -void free_sftp_dirents(SFTP_DIRENT **s); +void free_sftp_dirents(SFTP_DIRENT **); /* Delete file 'path' */ -int do_rm(int fd_in, int fd_out, char *path); +int do_rm(struct sftp_conn *, char *); /* Create directory 'path' */ -int do_mkdir(int fd_in, int fd_out, char *path, Attrib *a); +int do_mkdir(struct sftp_conn *, char *, Attrib *); /* Remove directory 'path' */ -int do_rmdir(int fd_in, int fd_out, char *path); +int do_rmdir(struct sftp_conn *, char *); /* Get file attributes of 'path' (follows symlinks) */ -Attrib *do_stat(int fd_in, int fd_out, char *path, int quiet); +Attrib *do_stat(struct sftp_conn *, char *, int); /* Get file attributes of 'path' (does not follow symlinks) */ -Attrib *do_lstat(int fd_in, int fd_out, char *path, int quiet); +Attrib *do_lstat(struct sftp_conn *, char *, int); /* Get file attributes of open file 'handle' */ -Attrib *do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, - int quiet); +Attrib *do_fstat(struct sftp_conn *, char *, u_int, int); /* Set file attributes of 'path' */ -int do_setstat(int fd_in, int fd_out, char *path, Attrib *a); +int do_setstat(struct sftp_conn *, char *, Attrib *); /* Set file attributes of open file 'handle' */ -int do_fsetstat(int fd_in, int fd_out, char *handle, - u_int handle_len, Attrib *a); +int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); /* Canonicalise 'path' - caller must free result */ -char *do_realpath(int fd_in, int fd_out, char *path); +char *do_realpath(struct sftp_conn *, char *); /* Rename 'oldpath' to 'newpath' */ -int do_rename(int fd_in, int fd_out, char *oldpath, char *newpath); +int do_rename(struct sftp_conn *, char *, char *); /* Rename 'oldpath' to 'newpath' */ -int do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath); +int do_symlink(struct sftp_conn *, char *, char *); /* Return target of symlink 'path' - caller must free result */ -char *do_readlink(int fd_in, int fd_out, char *path); +char *do_readlink(struct sftp_conn *, char *); /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ @@ -96,12 +99,12 @@ * Download 'remote_path' to 'local_path'. Preserve permissions and times * if 'pflag' is set */ -int do_download(int fd_in, int fd_out, char *remote_path, char *local_path, - int pflag); +int do_download(struct sftp_conn *, char *, char *, int); /* * Upload 'local_path' to 'remote_path'. Preserve permissions and times * if 'pflag' is set */ -int do_upload(int fd_in, int fd_out, char *local_path, char *remote_path, - int pflag); +int do_upload(struct sftp_conn *, char *, char *, int); + +#endif Index: src/crypto/openssh/sftp-common.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-common.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-common.c --- src/crypto/openssh/sftp-common.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-common.c 30 Jun 2002 11:38:00 -0000 @@ -24,17 +24,17 @@ */ #include "includes.h" -RCSID("$OpenBSD: sftp-common.c,v 1.2 2001/02/06 23:50:10 markus Exp $"); +RCSID("$OpenBSD: sftp-common.c,v 1.6 2002/06/23 09:30:14 deraadt Exp $"); #include "buffer.h" #include "bufaux.h" -#include "getput.h" #include "log.h" #include "xmalloc.h" #include "sftp.h" #include "sftp-common.h" +/* Clear contents of attributes structure */ void attrib_clear(Attrib *a) { @@ -47,6 +47,7 @@ a->mtime = 0; } +/* Convert from struct stat to filexfer attribs */ void stat_to_attrib(struct stat *st, Attrib *a) { @@ -64,10 +65,12 @@ a->mtime = st->st_mtime; } +/* Decode attributes in buffer */ Attrib * decode_attrib(Buffer *b) { static Attrib a; + attrib_clear(&a); a.flags = buffer_get_int(b); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) @@ -86,6 +89,7 @@ if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { char *type, *data; int i, count; + count = buffer_get_int(b); for (i = 0; i < count; i++) { type = buffer_get_string(b, NULL); @@ -98,6 +102,7 @@ return &a; } +/* Encode attributes to buffer */ void encode_attrib(Buffer *b, Attrib *a) { @@ -116,6 +121,7 @@ } } +/* Convert from SSH2_FX_ status to text error message */ const char * fx2txt(int status) { @@ -140,7 +146,6 @@ return("Operation unsupported"); default: return("Unknown status"); - }; + } /* NOTREACHED */ } - Index: src/crypto/openssh/sftp-common.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-common.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-common.h --- src/crypto/openssh/sftp-common.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-common.h 30 Jun 2002 11:38:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-common.h,v 1.1 2001/02/04 11:11:54 djm Exp $ */ +/* $OpenBSD: sftp-common.h,v 1.3 2001/06/26 17:27:24 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -38,18 +38,9 @@ u_int32_t mtime; }; -/* Clear contents of attributes structure */ -void attrib_clear(Attrib *a); - -/* Convert from struct stat to filexfer attribs */ -void stat_to_attrib(struct stat *st, Attrib *a); - -/* Decode attributes in buffer */ -Attrib *decode_attrib(Buffer *b); - -/* Encode attributes to buffer */ -void encode_attrib(Buffer *b, Attrib *a); - -/* Convert from SSH2_FX_ status to text error message */ -const char *fx2txt(int status); +void attrib_clear(Attrib *); +void stat_to_attrib(struct stat *, Attrib *); +Attrib *decode_attrib(Buffer *); +void encode_attrib(Buffer *, Attrib *); +const char *fx2txt(int); Index: src/crypto/openssh/sftp-glob.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-glob.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-glob.c --- src/crypto/openssh/sftp-glob.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-glob.c 30 Jun 2002 11:38:00 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,18 +23,12 @@ */ #include "includes.h" -RCSID("$OpenBSD: sftp-glob.c,v 1.5 2001/04/15 08:43:46 markus Exp $"); +RCSID("$OpenBSD: sftp-glob.c,v 1.10 2002/02/13 00:59:23 djm Exp $"); -#include - -#include "ssh.h" #include "buffer.h" #include "bufaux.h" -#include "getput.h" #include "xmalloc.h" #include "log.h" -#include "atomicio.h" -#include "pathnames.h" #include "sftp.h" #include "sftp-common.h" @@ -47,17 +41,17 @@ }; static struct { - int fd_in; - int fd_out; + struct sftp_conn *conn; } cur; -void *fudge_opendir(const char *path) +static void * +fudge_opendir(const char *path) { struct SFTP_OPENDIR *r; - + r = xmalloc(sizeof(*r)); - - if (do_readdir(cur.fd_in, cur.fd_out, (char*)path, &r->dir)) + + if (do_readdir(cur.conn, (char*)path, &r->dir)) return(NULL); r->offset = 0; @@ -65,30 +59,57 @@ return((void*)r); } -struct dirent *fudge_readdir(struct SFTP_OPENDIR *od) +static struct dirent * +fudge_readdir(struct SFTP_OPENDIR *od) { - static struct dirent ret; + /* Solaris needs sizeof(dirent) + path length (see below) */ + static char buf[sizeof(struct dirent) + MAXPATHLEN]; + struct dirent *ret = (struct dirent *)buf; +#ifdef __GNU_LIBRARY__ + static int inum = 1; +#endif /* __GNU_LIBRARY__ */ if (od->dir[od->offset] == NULL) return(NULL); - memset(&ret, 0, sizeof(ret)); - strlcpy(ret.d_name, od->dir[od->offset++]->filename, - sizeof(ret.d_name)); + memset(buf, 0, sizeof(buf)); + + /* + * Solaris defines dirent->d_name as a one byte array and expects + * you to hack around it. + */ +#ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME + strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); +#else + strlcpy(ret->d_name, od->dir[od->offset++]->filename, + sizeof(ret->d_name)); +#endif +#ifdef __GNU_LIBRARY__ + /* + * Idiot glibc uses extensions to struct dirent for readdir with + * ALTDIRFUNCs. Not that this is documented anywhere but the + * source... Fake an inode number to appease it. + */ + ret->d_ino = inum++; + if (!inum) + inum = 1; +#endif /* __GNU_LIBRARY__ */ - return(&ret); + return(ret); } -void fudge_closedir(struct SFTP_OPENDIR *od) +static void +fudge_closedir(struct SFTP_OPENDIR *od) { free_sftp_dirents(od->dir); xfree(od); } -void attrib_to_stat(Attrib *a, struct stat *st) +static void +attrib_to_stat(Attrib *a, struct stat *st) { memset(st, 0, sizeof(*st)); - + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) st->st_size = a->size; if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { @@ -103,44 +124,44 @@ } } -int fudge_lstat(const char *path, struct stat *st) +static int +fudge_lstat(const char *path, struct stat *st) { Attrib *a; - - if (!(a = do_lstat(cur.fd_in, cur.fd_out, (char*)path, 0))) + + if (!(a = do_lstat(cur.conn, (char*)path, 0))) return(-1); - + attrib_to_stat(a, st); - + return(0); } -int fudge_stat(const char *path, struct stat *st) +static int +fudge_stat(const char *path, struct stat *st) { Attrib *a; - - if (!(a = do_stat(cur.fd_in, cur.fd_out, (char*)path, 0))) + + if (!(a = do_stat(cur.conn, (char*)path, 0))) return(-1); - + attrib_to_stat(a, st); - + return(0); } int -remote_glob(int fd_in, int fd_out, const char *pattern, int flags, +remote_glob(struct sftp_conn *conn, const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { - pglob->gl_opendir = (void*)fudge_opendir; - pglob->gl_readdir = (void*)fudge_readdir; - pglob->gl_closedir = (void*)fudge_closedir; + pglob->gl_opendir = fudge_opendir; + pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; + pglob->gl_closedir = (void (*)(void *))fudge_closedir; pglob->gl_lstat = fudge_lstat; pglob->gl_stat = fudge_stat; - + memset(&cur, 0, sizeof(cur)); - cur.fd_in = fd_in; - cur.fd_out = fd_out; + cur.conn = conn; - return(glob(pattern, flags | GLOB_ALTDIRFUNC, (void*)errfunc, - pglob)); + return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); } Index: src/crypto/openssh/sftp-glob.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-glob.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-glob.h --- src/crypto/openssh/sftp-glob.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-glob.h 30 Jun 2002 11:38:00 -0000 @@ -1,7 +1,7 @@ -/* $OpenBSD: sftp-glob.h,v 1.3 2001/04/15 08:43:46 markus Exp $ */ +/* $OpenBSD: sftp-glob.h,v 1.7 2002/03/19 10:49:35 markus Exp $ */ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,13 @@ /* Remote sftp filename globbing */ +#ifndef _SFTP_GLOB_H +#define _SFTP_GLOB_H + +#include "sftp-client.h" + int -remote_glob(int fd_in, int fd_out, const char *pattern, int flags, - int (*errfunc)(const char *, int), glob_t *pglob); +remote_glob(struct sftp_conn *, const char *, int, + int (*)(const char *, int), glob_t *); +#endif Index: src/crypto/openssh/sftp-int.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-int.c,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 sftp-int.c --- src/crypto/openssh/sftp-int.c 28 Jan 2002 00:04:02 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/sftp-int.c 30 Jun 2002 11:38:01 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,9 +26,7 @@ /* XXX: recursive operations */ #include "includes.h" -RCSID("$OpenBSD: sftp-int.c,v 1.36 2001/04/15 08:43:46 markus Exp $"); - -#include +RCSID("$OpenBSD: sftp-int.c,v 1.47 2002/06/23 09:30:14 deraadt Exp $"); #include "buffer.h" #include "xmalloc.h" @@ -44,8 +42,11 @@ /* File to read commands from */ extern FILE *infile; -/* Version of server we are speaking to */ -int version; +/* Size of buffer used when copying files */ +extern size_t copy_buffer_len; + +/* Number of concurrent outstanding requests */ +extern int num_requests; /* Seperators for interactive commands */ #define WHITESPACE " \t\r\n" @@ -80,6 +81,7 @@ }; const struct CMD cmds[] = { + { "bye", I_QUIT }, { "cd", I_CHDIR }, { "chdir", I_CHDIR }, { "chgrp", I_CHGRP }, @@ -113,7 +115,7 @@ { NULL, -1} }; -void +static void help(void) { printf("Available commands:\n"); @@ -145,7 +147,7 @@ printf("? Synonym for help\n"); } -void +static void local_do_shell(const char *args) { int status; @@ -165,24 +167,25 @@ /* XXX: child has pipe fds to ssh subproc open - issue? */ if (args) { debug3("Executing %s -c \"%s\"", shell, args); - execl(shell, shell, "-c", args, NULL); + execl(shell, shell, "-c", args, (char *)NULL); } else { debug3("Executing %s", shell); - execl(shell, shell, NULL); + execl(shell, shell, (char *)NULL); } fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell, strerror(errno)); _exit(1); } - if (waitpid(pid, &status, 0) == -1) - fatal("Couldn't wait for child: %s", strerror(errno)); + while (waitpid(pid, &status, 0) == -1) + if (errno != EINTR) + fatal("Couldn't wait for child: %s", strerror(errno)); if (!WIFEXITED(status)) error("Shell exited abormally"); else if (WEXITSTATUS(status)) error("Shell exited with status %d", WEXITSTATUS(status)); } -void +static void local_do_ls(const char *args) { if (!args || !*args) @@ -198,7 +201,7 @@ } } -char * +static char * path_append(char *p1, char *p2) { char *ret; @@ -206,13 +209,14 @@ ret = xmalloc(len); strlcpy(ret, p1, len); - strlcat(ret, "/", len); + if (strcmp(p1, "/") != 0) + strlcat(ret, "/", len); strlcat(ret, p2, len); return(ret); } -char * +static char * make_absolute(char *p, char *pwd) { char *abs; @@ -226,7 +230,7 @@ return(p); } -int +static int infer_path(const char *p, char **ifp) { char *cp; @@ -246,7 +250,7 @@ return(0); } -int +static int parse_getput_flags(const char **cpp, int *pflag) { const char *cp = *cpp; @@ -269,7 +273,7 @@ return(0); } -int +static int get_pathname(const char **cpp, char **path) { const char *cp = *cpp, *end; @@ -317,7 +321,7 @@ return (-1); } -int +static int is_dir(char *path) { struct stat sb; @@ -329,21 +333,21 @@ return(sb.st_mode & S_IFDIR); } -int -remote_is_dir(int in, int out, char *path) +static int +remote_is_dir(struct sftp_conn *conn, char *path) { Attrib *a; /* XXX: report errors? */ - if ((a = do_stat(in, out, path, 1)) == NULL) + if ((a = do_stat(conn, path, 1)) == NULL) return(0); if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) return(0); return(a->perm & S_IFDIR); } -int -process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) +static int +process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) { char *abs_src = NULL; char *abs_dst = NULL; @@ -357,7 +361,7 @@ memset(&g, 0, sizeof(g)); debug3("Looking up %s", abs_src); - if (remote_glob(in, out, abs_src, 0, NULL, &g)) { + if (remote_glob(conn, abs_src, 0, NULL, &g)) { error("File \"%s\" not found.", abs_src); err = -1; goto out; @@ -381,7 +385,7 @@ goto out; } printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst); - err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag); + err = do_download(conn, g.gl_pathv[0], abs_dst, pflag); goto out; } @@ -393,7 +397,7 @@ goto out; } - for(i = 0; g.gl_pathv[i]; i++) { + for (i = 0; g.gl_pathv[i]; i++) { if (infer_path(g.gl_pathv[i], &tmp)) { err = -1; goto out; @@ -405,7 +409,7 @@ abs_dst = tmp; printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); - if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag) == -1) + if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1) err = -1; xfree(abs_dst); abs_dst = NULL; @@ -419,8 +423,8 @@ return(err); } -int -process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) +static int +process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) { char *tmp_dst = NULL; char *abs_dst = NULL; @@ -436,7 +440,7 @@ memset(&g, 0, sizeof(g)); debug3("Looking up %s", src); - if (glob(src, 0, NULL, &g) != 0 || g.gl_matchc == 0) { + if (glob(src, 0, NULL, &g)) { error("File \"%s\" not found.", src); err = -1; goto out; @@ -446,7 +450,7 @@ if (g.gl_pathv[0] && g.gl_matchc == 1) { if (tmp_dst) { /* If directory specified, append filename */ - if (remote_is_dir(in, out, tmp_dst)) { + if (remote_is_dir(conn, tmp_dst)) { if (infer_path(g.gl_pathv[0], &tmp)) { err = 1; goto out; @@ -463,19 +467,19 @@ abs_dst = make_absolute(abs_dst, pwd); } printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst); - err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag); + err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag); goto out; } /* Multiple matches, dst may be directory or unspecified */ - if (tmp_dst && !remote_is_dir(in, out, tmp_dst)) { + if (tmp_dst && !remote_is_dir(conn, tmp_dst)) { error("Multiple files match, but \"%s\" is not a directory", tmp_dst); err = -1; goto out; } - for(i = 0; g.gl_pathv[i]; i++) { + for (i = 0; g.gl_pathv[i]; i++) { if (infer_path(g.gl_pathv[i], &tmp)) { err = -1; goto out; @@ -487,7 +491,7 @@ abs_dst = make_absolute(tmp, pwd); printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); - if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag) == -1) + if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1) err = -1; } @@ -499,7 +503,7 @@ return(err); } -int +static int parse_args(const char **cpp, int *pflag, unsigned long *n_arg, char **path1, char **path2) { @@ -517,7 +521,7 @@ return(-1); /* Figure out which command we have */ - for(i = 0; cmds[i].c; i++) { + for (i = 0; cmds[i].c; i++) { int cmdlen = strlen(cmds[i].c); /* Check for command followed by whitespace */ @@ -644,8 +648,8 @@ return(cmdnum); } -int -parse_dispatch_command(int in, int out, const char *cmd, char **pwd) +static int +parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) { char *path1, *path2, *tmp; int pflag, cmdnum, i; @@ -665,32 +669,26 @@ case -1: break; case I_GET: - err = process_get(in, out, path1, path2, *pwd, pflag); + err = process_get(conn, path1, path2, *pwd, pflag); break; case I_PUT: - err = process_put(in, out, path1, path2, *pwd, pflag); + err = process_put(conn, path1, path2, *pwd, pflag); break; case I_RENAME: path1 = make_absolute(path1, *pwd); path2 = make_absolute(path2, *pwd); - err = do_rename(in, out, path1, path2); + err = do_rename(conn, path1, path2); break; case I_SYMLINK: - if (version < 3) { - error("The server (version %d) does not support " - "this operation", version); - err = -1; - } else { - path2 = make_absolute(path2, *pwd); - err = do_symlink(in, out, path1, path2); - } + path2 = make_absolute(path2, *pwd); + err = do_symlink(conn, path1, path2); break; case I_RM: path1 = make_absolute(path1, *pwd); - remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); - for(i = 0; g.gl_pathv[i]; i++) { + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i]; i++) { printf("Removing %s\n", g.gl_pathv[i]); - if (do_rm(in, out, g.gl_pathv[i]) == -1) + if (do_rm(conn, g.gl_pathv[i]) == -1) err = -1; } break; @@ -699,19 +697,19 @@ attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = 0777; - err = do_mkdir(in, out, path1, &a); + err = do_mkdir(conn, path1, &a); break; case I_RMDIR: path1 = make_absolute(path1, *pwd); - err = do_rmdir(in, out, path1); + err = do_rmdir(conn, path1); break; case I_CHDIR: path1 = make_absolute(path1, *pwd); - if ((tmp = do_realpath(in, out, path1)) == NULL) { + if ((tmp = do_realpath(conn, path1)) == NULL) { err = 1; break; } - if ((aa = do_stat(in, out, tmp, 0)) == NULL) { + if ((aa = do_stat(conn, tmp, 0)) == NULL) { xfree(tmp); err = 1; break; @@ -734,22 +732,22 @@ break; case I_LS: if (!path1) { - do_ls(in, out, *pwd); + do_ls(conn, *pwd); break; } path1 = make_absolute(path1, *pwd); - if ((tmp = do_realpath(in, out, path1)) == NULL) + if ((tmp = do_realpath(conn, path1)) == NULL) break; xfree(path1); path1 = tmp; - if ((aa = do_stat(in, out, path1, 0)) == NULL) + if ((aa = do_stat(conn, path1, 0)) == NULL) break; if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && !S_ISDIR(aa->perm)) { error("Can't ls: \"%s\" is not a directory", path1); break; } - do_ls(in, out, path1); + do_ls(conn, path1); break; case I_LCHDIR: if (chdir(path1) == -1) { @@ -780,17 +778,17 @@ attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = n_arg; - remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); - for(i = 0; g.gl_pathv[i]; i++) { + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i]; i++) { printf("Changing mode on %s\n", g.gl_pathv[i]); - do_setstat(in, out, g.gl_pathv[i], &a); + do_setstat(conn, g.gl_pathv[i], &a); } break; case I_CHOWN: path1 = make_absolute(path1, *pwd); - remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); - for(i = 0; g.gl_pathv[i]; i++) { - if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i]; i++) { + if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) continue; if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { error("Can't get current ownership of " @@ -800,14 +798,14 @@ printf("Changing owner on %s\n", g.gl_pathv[i]); aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; aa->uid = n_arg; - do_setstat(in, out, g.gl_pathv[i], aa); + do_setstat(conn, g.gl_pathv[i], aa); } break; case I_CHGRP: path1 = make_absolute(path1, *pwd); - remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); - for(i = 0; g.gl_pathv[i]; i++) { - if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) + remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); + for (i = 0; g.gl_pathv[i]; i++) { + if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) continue; if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { error("Can't get current ownership of " @@ -817,7 +815,7 @@ printf("Changing group on %s\n", g.gl_pathv[i]); aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; aa->gid = n_arg; - do_setstat(in, out, g.gl_pathv[i], aa); + do_setstat(conn, g.gl_pathv[i], aa); } break; case I_PWD: @@ -837,7 +835,7 @@ help(); break; case I_VERSION: - printf("SFTP protocol version %d\n", version); + printf("SFTP protocol version %u\n", sftp_proto_version(conn)); break; default: fatal("%d is not implemented", cmdnum); @@ -863,12 +861,13 @@ char *pwd; char *dir = NULL; char cmd[2048]; + struct sftp_conn *conn; - version = do_init(fd_in, fd_out); - if (version == -1) + conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); + if (conn == NULL) fatal("Couldn't initialise connection to server"); - pwd = do_realpath(fd_in, fd_out, "."); + pwd = do_realpath(conn, "."); if (pwd == NULL) fatal("Need cwd"); @@ -876,10 +875,10 @@ dir = xstrdup(file1); dir = make_absolute(dir, pwd); - if (remote_is_dir(fd_in, fd_out, dir) && file2 == NULL) { + if (remote_is_dir(conn, dir) && file2 == NULL) { printf("Changing to: %s\n", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); - parse_dispatch_command(fd_in, fd_out, cmd, &pwd); + parse_dispatch_command(conn, cmd, &pwd); } else { if (file2 == NULL) snprintf(cmd, sizeof cmd, "get %s", dir); @@ -887,14 +886,21 @@ snprintf(cmd, sizeof cmd, "get %s %s", dir, file2); - parse_dispatch_command(fd_in, fd_out, cmd, &pwd); + parse_dispatch_command(conn, cmd, &pwd); + xfree(dir); return; } + xfree(dir); } +#if HAVE_SETVBUF setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); +#else + setlinebuf(stdout); + setlinebuf(infile); +#endif - for(;;) { + for (;;) { char *cp; printf("sftp> "); @@ -910,7 +916,7 @@ if (cp) *cp = '\0'; - if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd)) + if (parse_dispatch_command(conn, cmd, &pwd)) break; } xfree(pwd); Index: src/crypto/openssh/sftp-int.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-int.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp-int.h --- src/crypto/openssh/sftp-int.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp-int.h 30 Jun 2002 11:38:01 -0000 @@ -1,7 +1,7 @@ -/* $OpenBSD: sftp-int.h,v 1.2 2001/04/12 23:17:54 mouring Exp $ */ +/* $OpenBSD: sftp-int.h,v 1.5 2002/02/13 00:59:23 djm Exp $ */ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,4 +24,4 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -void interactive_loop(int fd_in, int fd_out, char *file1, char *file2); +void interactive_loop(int, int, char *, char *); Index: src/crypto/openssh/sftp-server.8 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-server.8,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 sftp-server.8 --- src/crypto/openssh/sftp-server.8 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/sftp-server.8 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp-server.8,v 1.6 2001/04/22 13:32:26 markus Exp $ +.\" $OpenBSD: sftp-server.8,v 1.8 2001/06/23 05:57:08 deraadt Exp $ .\" .\" Copyright (c) 2000 Markus Friedl. All rights reserved. .\" @@ -59,5 +59,4 @@ Markus Friedl .Sh HISTORY .Nm -first appeared in -.Ox 2.8 . +first appeared in OpenBSD 2.8 . Index: src/crypto/openssh/sftp-server.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp-server.c,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 sftp-server.c --- src/crypto/openssh/sftp-server.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/sftp-server.c 30 Jun 2002 11:38:01 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: sftp-server.c,v 1.25 2001/04/05 10:42:53 markus Exp $"); +RCSID("$OpenBSD: sftp-server.c,v 1.37 2002/06/24 17:57:20 deraadt Exp $"); #include "buffer.h" #include "bufaux.h" @@ -39,6 +39,12 @@ #define get_string(lenp) buffer_get_string(&iqueue, lenp); #define TRACE debug +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif + /* input and output queue */ Buffer iqueue; Buffer oqueue; @@ -56,7 +62,7 @@ Attrib attrib; }; -int +static int errno_to_portable(int unixerrno) { int ret = 0; @@ -87,7 +93,7 @@ return ret; } -int +static int flags_from_portable(int pflags) { int flags = 0; @@ -109,7 +115,7 @@ return flags; } -Attrib * +static Attrib * get_attrib(void) { return decode_attrib(&iqueue); @@ -133,21 +139,21 @@ Handle handles[100]; -void +static void handle_init(void) { int i; - for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) + for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) handles[i].use = HANDLE_UNUSED; } -int +static int handle_new(int use, char *name, int fd, DIR *dirp) { int i; - for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) { + for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) { if (handles[i].use == HANDLE_UNUSED) { handles[i].use = use; handles[i].dirp = dirp; @@ -159,14 +165,14 @@ return -1; } -int +static int handle_is_ok(int i, int type) { return i >= 0 && i < sizeof(handles)/sizeof(Handle) && handles[i].use == type; } -int +static int handle_to_string(int handle, char **stringp, int *hlenp) { if (stringp == NULL || hlenp == NULL) @@ -177,7 +183,7 @@ return 0; } -int +static int handle_from_string(char *handle, u_int hlen) { int val; @@ -191,7 +197,7 @@ return -1; } -char * +static char * handle_to_name(int handle) { if (handle_is_ok(handle, HANDLE_DIR)|| @@ -200,7 +206,7 @@ return NULL; } -DIR * +static DIR * handle_to_dir(int handle) { if (handle_is_ok(handle, HANDLE_DIR)) @@ -208,7 +214,7 @@ return NULL; } -int +static int handle_to_fd(int handle) { if (handle_is_ok(handle, HANDLE_FILE)) @@ -216,7 +222,7 @@ return -1; } -int +static int handle_close(int handle) { int ret = -1; @@ -233,7 +239,7 @@ return ret; } -int +static int get_handle(void) { char *handle; @@ -249,7 +255,7 @@ /* send replies */ -void +static void send_msg(Buffer *m) { int mlen = buffer_len(m); @@ -259,7 +265,7 @@ buffer_consume(m, mlen); } -void +static void send_status(u_int32_t id, u_int32_t error) { Buffer msg; @@ -276,7 +282,7 @@ "Unknown error" /* Others */ }; - TRACE("sent status id %d error %d", id, error); + TRACE("sent status id %u error %u", id, error); buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_STATUS); buffer_put_int(&msg, id); @@ -289,7 +295,7 @@ send_msg(&msg); buffer_free(&msg); } -void +static void send_data_or_handle(char type, u_int32_t id, char *data, int dlen) { Buffer msg; @@ -302,26 +308,26 @@ buffer_free(&msg); } -void +static void send_data(u_int32_t id, char *data, int dlen) { - TRACE("sent data id %d len %d", id, dlen); + TRACE("sent data id %u len %d", id, dlen); send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); } -void +static void send_handle(u_int32_t id, int handle) { char *string; int hlen; handle_to_string(handle, &string, &hlen); - TRACE("sent handle id %d handle %d", id, handle); + TRACE("sent handle id %u handle %d", id, handle); send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); xfree(string); } -void +static void send_names(u_int32_t id, int count, Stat *stats) { Buffer msg; @@ -331,7 +337,7 @@ buffer_put_char(&msg, SSH2_FXP_NAME); buffer_put_int(&msg, id); buffer_put_int(&msg, count); - TRACE("sent names id %d count %d", id, count); + TRACE("sent names id %u count %d", id, count); for (i = 0; i < count; i++) { buffer_put_cstring(&msg, stats[i].name); buffer_put_cstring(&msg, stats[i].long_name); @@ -341,12 +347,12 @@ buffer_free(&msg); } -void +static void send_attrib(u_int32_t id, Attrib *a) { Buffer msg; - TRACE("sent attrib id %d have 0x%x", id, a->flags); + TRACE("sent attrib id %u have 0x%x", id, a->flags); buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_ATTRS); buffer_put_int(&msg, id); @@ -357,12 +363,12 @@ /* parse incoming */ -void +static void process_init(void) { Buffer msg; - version = buffer_get_int(&iqueue); + version = get_int(); TRACE("client version %d", version); buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_VERSION); @@ -371,7 +377,7 @@ buffer_free(&msg); } -void +static void process_open(void) { u_int32_t id, pflags; @@ -385,7 +391,7 @@ a = get_attrib(); flags = flags_from_portable(pflags); mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; - TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode); + TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode); fd = open(name, flags, mode); if (fd < 0) { status = errno_to_portable(errno); @@ -403,7 +409,7 @@ xfree(name); } -void +static void process_close(void) { u_int32_t id; @@ -411,13 +417,13 @@ id = get_int(); handle = get_handle(); - TRACE("close id %d handle %d", id, handle); + TRACE("close id %u handle %d", id, handle); ret = handle_close(handle); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); } -void +static void process_read(void) { char buf[64*1024]; @@ -430,8 +436,8 @@ off = get_int64(); len = get_int(); - TRACE("read id %d handle %d off %llu len %d", id, handle, - (unsigned long long)off, len); + TRACE("read id %u handle %d off %llu len %d", id, handle, + (u_int64_t)off, len); if (len > sizeof buf) { len = sizeof buf; log("read change len %d", len); @@ -457,7 +463,7 @@ send_status(id, status); } -void +static void process_write(void) { u_int32_t id; @@ -471,8 +477,8 @@ off = get_int64(); data = get_string(&len); - TRACE("write id %d handle %d off %llu len %d", id, handle, - (unsigned long long)off, len); + TRACE("write id %u handle %d off %llu len %d", id, handle, + (u_int64_t)off, len); fd = handle_to_fd(handle); if (fd >= 0) { if (lseek(fd, off, SEEK_SET) < 0) { @@ -495,7 +501,7 @@ xfree(data); } -void +static void process_do_stat(int do_lstat) { Attrib a; @@ -506,7 +512,7 @@ id = get_int(); name = get_string(NULL); - TRACE("%sstat id %d name %s", do_lstat ? "l" : "", id, name); + TRACE("%sstat id %u name %s", do_lstat ? "l" : "", id, name); ret = do_lstat ? lstat(name, &st) : stat(name, &st); if (ret < 0) { status = errno_to_portable(errno); @@ -520,19 +526,19 @@ xfree(name); } -void +static void process_stat(void) { process_do_stat(0); } -void +static void process_lstat(void) { process_do_stat(1); } -void +static void process_fstat(void) { Attrib a; @@ -542,7 +548,7 @@ id = get_int(); handle = get_handle(); - TRACE("fstat id %d handle %d", id, handle); + TRACE("fstat id %u handle %d", id, handle); fd = handle_to_fd(handle); if (fd >= 0) { ret = fstat(fd, &st); @@ -558,7 +564,7 @@ send_status(id, status); } -struct timeval * +static struct timeval * attrib_to_tv(Attrib *a) { static struct timeval tv[2]; @@ -570,19 +576,23 @@ return tv; } -void +static void process_setstat(void) { Attrib *a; u_int32_t id; char *name; - int ret; - int status = SSH2_FX_OK; + int status = SSH2_FX_OK, ret; id = get_int(); name = get_string(NULL); a = get_attrib(); - TRACE("setstat id %d name %s", id, name); + TRACE("setstat id %u name %s", id, name); + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { + ret = truncate(name, a->size); + if (ret == -1) + status = errno_to_portable(errno); + } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { ret = chmod(name, a->perm & 0777); if (ret == -1) @@ -602,34 +612,53 @@ xfree(name); } -void +static void process_fsetstat(void) { Attrib *a; u_int32_t id; int handle, fd, ret; int status = SSH2_FX_OK; + char *name; id = get_int(); handle = get_handle(); a = get_attrib(); - TRACE("fsetstat id %d handle %d", id, handle); + TRACE("fsetstat id %u handle %d", id, handle); fd = handle_to_fd(handle); - if (fd < 0) { + name = handle_to_name(handle); + if (fd < 0 || name == NULL) { status = SSH2_FX_FAILURE; } else { + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { + ret = ftruncate(fd, a->size); + if (ret == -1) + status = errno_to_portable(errno); + } if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { +#ifdef HAVE_FCHMOD ret = fchmod(fd, a->perm & 0777); +#else + ret = chmod(name, a->perm & 0777); +#endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { +#ifdef HAVE_FUTIMES ret = futimes(fd, attrib_to_tv(a)); +#else + ret = utimes(name, attrib_to_tv(a)); +#endif if (ret == -1) status = errno_to_portable(errno); } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { +#ifdef HAVE_FCHOWN ret = fchown(fd, a->uid, a->gid); +#else + ret = chown(name, a->uid, a->gid); +#endif if (ret == -1) status = errno_to_portable(errno); } @@ -637,7 +666,7 @@ send_status(id, status); } -void +static void process_opendir(void) { DIR *dirp = NULL; @@ -647,7 +676,7 @@ id = get_int(); path = get_string(NULL); - TRACE("opendir id %d path %s", id, path); + TRACE("opendir id %u path %s", id, path); dirp = opendir(path); if (dirp == NULL) { status = errno_to_portable(errno); @@ -669,10 +698,10 @@ /* * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh */ -char * +static char * ls_file(char *name, struct stat *st) { - int sz = 0; + int ulen, glen, sz = 0; struct passwd *pw; struct group *gr; struct tm *ltime = localtime(&st->st_mtime); @@ -683,13 +712,13 @@ if ((pw = getpwuid(st->st_uid)) != NULL) { user = pw->pw_name; } else { - snprintf(ubuf, sizeof ubuf, "%d", st->st_uid); + snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; } if ((gr = getgrgid(st->st_gid)) != NULL) { group = gr->gr_name; } else { - snprintf(gbuf, sizeof gbuf, "%d", st->st_gid); + snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); group = gbuf; } if (ltime != NULL) { @@ -700,12 +729,15 @@ } if (sz == 0) tbuf[0] = '\0'; - snprintf(buf, sizeof buf, "%s %3d %-8.8s %-8.8s %8llu %s %s", mode, - st->st_nlink, user, group, (unsigned long long)st->st_size, tbuf, name); + ulen = MAX(strlen(user), 8); + glen = MAX(strlen(group), 8); + snprintf(buf, sizeof buf, "%s %3d %-*s %-*s %8llu %s %s", mode, + st->st_nlink, ulen, user, glen, group, + (u_int64_t)st->st_size, tbuf, name); return xstrdup(buf); } -void +static void process_readdir(void) { DIR *dirp; @@ -716,7 +748,7 @@ id = get_int(); handle = get_handle(); - TRACE("readdir id %d handle %d", id, handle); + TRACE("readdir id %u handle %d", id, handle); dirp = handle_to_dir(handle); path = handle_to_name(handle); if (dirp == NULL || path == NULL) { @@ -726,6 +758,7 @@ char pathname[1024]; Stat *stats; int nstats = 10, count = 0, i; + stats = xmalloc(nstats * sizeof(Stat)); while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { @@ -733,8 +766,8 @@ stats = xrealloc(stats, nstats * sizeof(Stat)); } /* XXX OVERFLOW ? */ - snprintf(pathname, sizeof pathname, - "%s/%s", path, dp->d_name); + snprintf(pathname, sizeof pathname, "%s%s%s", path, + strcmp(path, "/") ? "/" : "", dp->d_name); if (lstat(pathname, &st) < 0) continue; stat_to_attrib(&st, &(stats[count].attrib)); @@ -748,7 +781,7 @@ } if (count > 0) { send_names(id, count, stats); - for(i = 0; i < count; i++) { + for (i = 0; i < count; i++) { xfree(stats[i].name); xfree(stats[i].long_name); } @@ -759,7 +792,7 @@ } } -void +static void process_remove(void) { char *name; @@ -769,14 +802,14 @@ id = get_int(); name = get_string(NULL); - TRACE("remove id %d name %s", id, name); + TRACE("remove id %u name %s", id, name); ret = unlink(name); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); xfree(name); } -void +static void process_mkdir(void) { Attrib *a; @@ -789,14 +822,14 @@ a = get_attrib(); mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm & 0777 : 0777; - TRACE("mkdir id %d name %s mode 0%o", id, name, mode); + TRACE("mkdir id %u name %s mode 0%o", id, name, mode); ret = mkdir(name, mode); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); xfree(name); } -void +static void process_rmdir(void) { u_int32_t id; @@ -805,14 +838,14 @@ id = get_int(); name = get_string(NULL); - TRACE("rmdir id %d name %s", id, name); + TRACE("rmdir id %u name %s", id, name); ret = rmdir(name); status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); xfree(name); } -void +static void process_realpath(void) { char resolvedname[MAXPATHLEN]; @@ -825,7 +858,7 @@ xfree(path); path = xstrdup("."); } - TRACE("realpath id %d path %s", id, path); + TRACE("realpath id %u path %s", id, path); if (realpath(path, resolvedname) == NULL) { send_status(id, errno_to_portable(errno)); } else { @@ -837,7 +870,7 @@ xfree(path); } -void +static void process_rename(void) { u_int32_t id; @@ -848,7 +881,7 @@ id = get_int(); oldpath = get_string(NULL); newpath = get_string(NULL); - TRACE("rename id %d old %s new %s", id, oldpath, newpath); + TRACE("rename id %u old %s new %s", id, oldpath, newpath); /* fail if 'newpath' exists */ if (stat(newpath, &st) == -1) { ret = rename(oldpath, newpath); @@ -859,22 +892,23 @@ xfree(newpath); } -void +static void process_readlink(void) { u_int32_t id; + int len; char link[MAXPATHLEN]; char *path; id = get_int(); path = get_string(NULL); - TRACE("readlink id %d path %s", id, path); - if (readlink(path, link, sizeof(link) - 1) == -1) + TRACE("readlink id %u path %s", id, path); + if ((len = readlink(path, link, sizeof(link) - 1)) == -1) send_status(id, errno_to_portable(errno)); else { Stat s; - - link[sizeof(link) - 1] = '\0'; + + link[len] = '\0'; attrib_clear(&s.attrib); s.name = s.long_name = link; send_names(id, 1, &s); @@ -882,7 +916,7 @@ xfree(path); } -void +static void process_symlink(void) { u_int32_t id; @@ -893,7 +927,7 @@ id = get_int(); oldpath = get_string(NULL); newpath = get_string(NULL); - TRACE("symlink id %d old %s new %s", id, oldpath, newpath); + TRACE("symlink id %u old %s new %s", id, oldpath, newpath); /* fail if 'newpath' exists */ if (stat(newpath, &st) == -1) { ret = symlink(oldpath, newpath); @@ -904,7 +938,7 @@ xfree(newpath); } -void +static void process_extended(void) { u_int32_t id; @@ -918,24 +952,28 @@ /* stolen from ssh-agent */ -void +static void process(void) { u_int msg_len; + u_int buf_len; + u_int consumed; u_int type; u_char *cp; - if (buffer_len(&iqueue) < 5) + buf_len = buffer_len(&iqueue); + if (buf_len < 5) return; /* Incomplete message. */ - cp = (u_char *) buffer_ptr(&iqueue); + cp = buffer_ptr(&iqueue); msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { error("bad message "); exit(11); } - if (buffer_len(&iqueue) < msg_len + 4) + if (buf_len < msg_len + 4) return; buffer_consume(&iqueue, 4); + buf_len -= 4; type = buffer_get_char(&iqueue); switch (type) { case SSH2_FXP_INIT: @@ -1002,6 +1040,14 @@ error("Unknown message %d", type); break; } + /* discard the remaining bytes from the current packet */ + if (buf_len < buffer_len(&iqueue)) + fatal("iqueue grows"); + consumed = buf_len - buffer_len(&iqueue); + if (msg_len < consumed) + fatal("msg_len %d < consumed %d", msg_len, consumed); + if (msg_len > consumed) + buffer_consume(&iqueue, msg_len - consumed); } int @@ -1013,6 +1059,7 @@ /* XXX should use getopt */ + __progname = get_progname(av[0]); handle_init(); #ifdef DEBUG_SFTP_SERVER @@ -1021,6 +1068,11 @@ in = dup(STDIN_FILENO); out = dup(STDOUT_FILENO); + +#ifdef HAVE_CYGWIN + setmode(in, O_BINARY); + setmode(out, O_BINARY); +#endif max = 0; if (in > max) Index: src/crypto/openssh/sftp.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp.1,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp.1 --- src/crypto/openssh/sftp.1 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp.1 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.17 2001/04/22 13:32:27 markus Exp $ +.\" $OpenBSD: sftp.1,v 1.35 2002/06/20 20:00:05 stevesk Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -30,14 +30,20 @@ .Nd Secure file transfer program .Sh SYNOPSIS .Nm sftp -.Op Fl vC +.Op Fl vC1 .Op Fl b Ar batchfile .Op Fl o Ar ssh_option -.Op Ar host +.Op Fl s Ar subsystem | sftp_server +.Op Fl B Ar buffer_size +.Op Fl F Ar ssh_config +.Op Fl P Ar sftp_server path +.Op Fl R Ar num_requests +.Op Fl S Ar program +.Ar host .Nm sftp .Op [\fIuser\fR@]\fIhost\fR[:\fIfile\fR [\fIfile\fR]] .Nm sftp -.Op [\fIuser\fR@]\fIhost\fR[:\fIdir\fR[\fI/\fR]] +.Op [\fIuser\fR@]\fIhost\fR[:\fIdir\fR[\fI/\fR]] .Sh DESCRIPTION .Nm is an interactive file transfer program, similar to @@ -49,12 +55,12 @@ compression. .Nm connects and logs into the specified -.Ar hostname , +.Ar host , then enters an interactive command mode. .Pp -The second usage format will fetch files automaticly if a non-interactive -authentication is used, else it do so after an interactive authentication -is used. +The second usage format will retrieve files automatically if a non-interactive +authentication method is used; otherwise it will do so after +successful interactive authentication. .Pp The last usage format allows the sftp client to start in a remote directory. .Pp @@ -68,49 +74,96 @@ Since it lacks user interaction it should be used in conjunction with non-interactive authentication. .Nm -will abort if any of the following -commands fail: -.Ic get , put , rename , ln , rm , mkdir , chdir , lchdir +will abort if any of the following +commands fail: +.Ic get , put , rename , ln , +.Ic rm , mkdir , chdir , lchdir and .Ic lmkdir . -.It Fl C -Enables compression (via ssh's -.Fl C -flag) .It Fl o Ar ssh_option -Specify an option to be directly passed to -.Xr ssh 1 . +Can be used to pass options to +.Nm ssh +in the format used in +.Xr ssh_config 5 . +This is useful for specifying options +for which there is no separate +.Nm sftp +command-line flag. For example, to specify an alternate +port use: +.Ic sftp -oPort=24 . +.It Fl s Ar subsystem | sftp_server +Specifies the SSH2 subsystem or the path for an sftp server +on the remote host. A path is useful for using sftp over +protocol version 1, or when the remote +.Nm sshd +does not have an sftp subsystem configured. .It Fl v Raise logging level. This option is also passed to ssh. +.It Fl B Ar buffer_size +Specify the size of the buffer that +.Nm +uses when transferring files. Larger buffers require fewer round trips at +the cost of higher memory consumption. The default is 32768 bytes. +.It Fl C +Enables compression (via ssh's +.Fl C +flag). +.It Fl F Ar ssh_config +Specifies an alternative +per-user configuration file for +.Nm ssh . +This option is directly passed to +.Xr ssh 1 . +.It Fl P Ar sftp_server path +Connect directly to a local +.Nm sftp-server +(rather than via +.Nm ssh ) +This option may be useful in debugging the client and server. +.It Fl R Ar num_requests +Specify how many requests may be outstanding at any one time. Increasing +this may slightly improve file transfer speed but will increase memory +usage. The default is 16 outstanding requests. +.It Fl S Ar program +Name of the +.Ar program +to use for the encrypted connection. +The program must understand +.Xr ssh 1 +options. +.It Fl 1 +Specify the use of protocol version 1. .El .Sh INTERACTIVE COMMANDS Once in interactive mode, .Nm -understands a set of commands similar to those of +understands a set of commands similar to those of .Xr ftp 1 . Commands are case insensitive and pathnames may be enclosed in quotes if they contain spaces. .Bl -tag -width Ds +.It Ic bye +Quit sftp. .It Ic cd Ar path -Change remote directory to +Change remote directory to .Ar path . .It Ic lcd Ar path -Change local directory to +Change local directory to .Ar path . .It Ic chgrp Ar grp Ar path -Change group of file +Change group of file .Ar path to .Ar grp . .Ar grp must be a numeric GID. .It Ic chmod Ar mode Ar path -Change permissions of file +Change permissions of file .Ar path to .Ar mode . .It Ic chown Ar own Ar path -Change owner of file +Change owner of file .Ar path to .Ar own . @@ -127,15 +180,15 @@ .Ar remote-path and store it on the local machine. If the local -path name is not specified, it is given the same name it has on the -remote machine. If the +path name is not specified, it is given the same name it has on the +remote machine. If the .Fl P flag is specified, then the file's full permission and access time are copied too. .It Ic help Display help text. .It Ic lls Op Ar ls-options Op Ar path -Display local directory listing of either +Display local directory listing of either .Ar path or current directory if .Ar path @@ -144,7 +197,7 @@ Create local directory specified by .Ar path . .It Ic ln Ar oldpath Ar newpath -Create a symbolic link from +Create a symbolic link from .Ar oldpath to .Ar newpath . @@ -157,7 +210,7 @@ .Ar path is not specified. .It Ic lumask Ar umask -Set local umask to +Set local umask to .Ar umask . .It Ic mkdir Ar path Create remote directory specified by @@ -169,8 +222,8 @@ .Xc Upload .Ar local-path -and store it on the remote machine. If the remote path name is not -specified, it is given the same name it has on the local machine. If the +and store it on the remote machine. If the remote path name is not +specified, it is given the same name it has on the local machine. If the .Fl P flag is specified, then the file's full permission and access time are copied too. @@ -190,12 +243,12 @@ Delete remote file specified by .Ar path . .It Ic symlink Ar oldpath Ar newpath -Create a symbolic link from +Create a symbolic link from .Ar oldpath to .Ar newpath . .It Ic ! Ar command -Execute +Execute .Ar command in local shell. .It Ic ! @@ -210,6 +263,7 @@ .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-keygen 1 , +.Xr ssh_config 5 , .Xr sftp-server 8 , .Xr sshd 8 .Rs Index: src/crypto/openssh/sftp.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp.c --- src/crypto/openssh/sftp.c 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp.c 30 Jun 2002 11:38:01 -0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,34 +24,39 @@ #include "includes.h" -RCSID("$OpenBSD: sftp.c,v 1.15 2001/04/16 02:31:44 mouring Exp $"); +RCSID("$OpenBSD: sftp.c,v 1.30 2002/06/23 09:30:14 deraadt Exp $"); -/* XXX: commandline mode */ /* XXX: short-form remote directory listings (like 'ls -C') */ #include "buffer.h" #include "xmalloc.h" #include "log.h" #include "pathnames.h" +#include "misc.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" #include "sftp-int.h" -#include "scp-common.h" +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif -int use_ssh1 = 0; -char *ssh_program = _PATH_SSH_PROGRAM; -char *sftp_server = NULL; FILE* infile; +size_t copy_buffer_len = 32768; +size_t num_requests = 16; -void -connect_to_server(char **args, int *in, int *out, pid_t *sshpid) +static void +connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid) { int c_in, c_out; + #ifdef USE_PIPES int pin[2], pout[2]; + if ((pipe(pin) == -1) || (pipe(pout) == -1)) fatal("pipe: %s", strerror(errno)); *in = pin[0]; @@ -60,6 +65,7 @@ c_out = pin[1]; #else /* USE_PIPES */ int inout[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) fatal("socketpair: %s", strerror(errno)); *in = *out = inout[0]; @@ -78,8 +84,8 @@ close(*out); close(c_in); close(c_out); - execv(ssh_program, args); - fprintf(stderr, "exec: %s: %s\n", ssh_program, strerror(errno)); + execv(path, args); + fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); exit(1); } @@ -87,93 +93,60 @@ close(c_out); } -char ** -make_ssh_args(char *add_arg) -{ - static char **args = NULL; - static int nargs = 0; - char debug_buf[4096]; - int i; - - /* Init args array */ - if (args == NULL) { - nargs = 2; - i = 0; - args = xmalloc(sizeof(*args) * nargs); - args[i++] = "ssh"; - args[i++] = NULL; - } - - /* If asked to add args, then do so and return */ - if (add_arg) { - i = nargs++ - 1; - args = xrealloc(args, sizeof(*args) * nargs); - args[i++] = add_arg; - args[i++] = NULL; - return(NULL); - } - - /* no subsystem if the server-spec contains a '/' */ - if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) - make_ssh_args("-s"); - make_ssh_args("-oForwardX11=no"); - make_ssh_args("-oForwardAgent=no"); - make_ssh_args(use_ssh1 ? "-oProtocol=1" : "-oProtocol=2"); - - /* Otherwise finish up and return the arg array */ - if (sftp_server != NULL) - make_ssh_args(sftp_server); - else - make_ssh_args("sftp"); - - /* XXX: overflow - doesn't grow debug_buf */ - debug_buf[0] = '\0'; - for(i = 0; args[i]; i++) { - if (i) - strlcat(debug_buf, " ", sizeof(debug_buf)); - - strlcat(debug_buf, args[i], sizeof(debug_buf)); - } - debug("SSH args \"%s\"", debug_buf); - - return(args); -} - -void +static void usage(void) { - fprintf(stderr, "usage: sftp [-1vC] [-b batchfile] [-osshopt=value] [user@]host[:file [file]]\n"); + extern char *__progname; + + fprintf(stderr, + "usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path] [-B buffer_size]\n" + " [-F config] [-P direct server path] [-S program]\n" + " [user@]host[:file [file]]\n", __progname); exit(1); } int main(int argc, char **argv) { - int in, out, ch, debug_level, compress_flag; + int in, out, ch; pid_t sshpid; - char *file1 = NULL; char *host, *userhost, *cp, *file2; - LogLevel ll; + int debug_level = 0, sshver = 2; + char *file1 = NULL, *sftp_server = NULL; + char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; + LogLevel ll = SYSLOG_LEVEL_INFO; + arglist args; extern int optind; extern char *optarg; + __progname = get_progname(argv[0]); + args.list = NULL; + addargs(&args, "ssh"); /* overwritten with ssh_program */ + addargs(&args, "-oFallBackToRsh no"); + addargs(&args, "-oForwardX11 no"); + addargs(&args, "-oForwardAgent no"); + addargs(&args, "-oClearAllForwardings yes"); + ll = SYSLOG_LEVEL_INFO; infile = stdin; /* Read from STDIN unless changed by -b */ - debug_level = compress_flag = 0; - while ((ch = getopt(argc, argv, "1hvCo:s:S:b:")) != -1) { + while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { switch (ch) { case 'C': - compress_flag = 1; + addargs(&args, "-C"); break; case 'v': - debug_level = MIN(3, debug_level + 1); + if (debug_level < 3) { + addargs(&args, "-v"); + ll = SYSLOG_LEVEL_DEBUG1 + debug_level; + } + debug_level++; break; + case 'F': case 'o': - make_ssh_args("-o"); - make_ssh_args(optarg); + addargs(&args, "-%c%s", ch, optarg); break; case '1': - use_ssh1 = 1; + sshver = 1; if (sftp_server == NULL) sftp_server = _PATH_SFTP_SERVER; break; @@ -191,81 +164,96 @@ } else fatal("Filename already specified."); break; + case 'P': + sftp_direct = optarg; + break; + case 'B': + copy_buffer_len = strtol(optarg, &cp, 10); + if (copy_buffer_len == 0 || *cp != '\0') + fatal("Invalid buffer size \"%s\"", optarg); + break; + case 'R': + num_requests = strtol(optarg, &cp, 10); + if (num_requests == 0 || *cp != '\0') + fatal("Invalid number of requests \"%s\"", + optarg); + break; case 'h': default: usage(); } } - if (optind == argc || argc > (optind + 2)) - usage(); - - userhost = xstrdup(argv[optind]); - file2 = argv[optind+1]; - - if ((cp = colon(userhost)) != NULL) { - *cp++ = '\0'; - file1 = cp; - } + log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); - if ((host = strchr(userhost, '@')) == NULL) - host = userhost; - else { - *host++ = '\0'; - if (!userhost[0]) { - fprintf(stderr, "Missing username\n"); + if (sftp_direct == NULL) { + if (optind == argc || argc > (optind + 2)) usage(); - } - make_ssh_args("-l"); - make_ssh_args(userhost); - } - host = cleanhostname(host); - if (!*host) { - fprintf(stderr, "Missing hostname\n"); - usage(); - } + userhost = xstrdup(argv[optind]); + file2 = argv[optind+1]; - /* Set up logging and debug '-d' arguments to ssh */ - ll = SYSLOG_LEVEL_INFO; - switch (debug_level) { - case 1: - ll = SYSLOG_LEVEL_DEBUG1; - make_ssh_args("-v"); - break; - case 2: - ll = SYSLOG_LEVEL_DEBUG2; - make_ssh_args("-v"); - make_ssh_args("-v"); - break; - case 3: - ll = SYSLOG_LEVEL_DEBUG3; - make_ssh_args("-v"); - make_ssh_args("-v"); - make_ssh_args("-v"); - break; - } - - if (compress_flag) - make_ssh_args("-C"); + if ((cp = colon(userhost)) != NULL) { + *cp++ = '\0'; + file1 = cp; + } - log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); + if ((host = strchr(userhost, '@')) == NULL) + host = userhost; + else { + *host++ = '\0'; + if (!userhost[0]) { + fprintf(stderr, "Missing username\n"); + usage(); + } + addargs(&args, "-l%s",userhost); + } - make_ssh_args(host); + host = cleanhostname(host); + if (!*host) { + fprintf(stderr, "Missing hostname\n"); + usage(); + } - fprintf(stderr, "Connecting to %s...\n", host); + addargs(&args, "-oProtocol %d", sshver); - connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid); + /* no subsystem if the server-spec contains a '/' */ + if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) + addargs(&args, "-s"); + + addargs(&args, "%s", host); + addargs(&args, "%s", (sftp_server != NULL ? + sftp_server : "sftp")); + args.list[0] = ssh_program; + + fprintf(stderr, "Connecting to %s...\n", host); + connect_to_server(ssh_program, args.list, &in, &out, + &sshpid); + } else { + args.list = NULL; + addargs(&args, "sftp-server"); + + fprintf(stderr, "Attaching to %s...\n", sftp_direct); + connect_to_server(sftp_direct, args.list, &in, &out, + &sshpid); + } interactive_loop(in, out, file1, file2); +#if !defined(USE_PIPES) + shutdown(in, SHUT_RDWR); + shutdown(out, SHUT_RDWR); +#endif + close(in); close(out); if (infile != stdin) fclose(infile); - if (waitpid(sshpid, NULL, 0) == -1) - fatal("Couldn't wait for ssh process: %s", strerror(errno)); + while (waitpid(sshpid, NULL, 0) == -1) + if (errno != EINTR) + fatal("Couldn't wait for ssh process: %s", + strerror(errno)); exit(0); } Index: src/crypto/openssh/sftp.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sftp.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sftp.h --- src/crypto/openssh/sftp.h 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sftp.h 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */ +/* $OpenBSD: sftp.h,v 1.4 2002/02/13 00:59:23 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -38,6 +38,7 @@ #define SSH2_FXP_READ 5 #define SSH2_FXP_WRITE 6 #define SSH2_FXP_LSTAT 7 +#define SSH2_FXP_STAT_VERSION_0 7 #define SSH2_FXP_FSTAT 8 #define SSH2_FXP_SETSTAT 9 #define SSH2_FXP_FSETSTAT 10 Index: src/crypto/openssh/ssh-add.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-add.1,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 ssh-add.1 --- src/crypto/openssh/ssh-add.1 28 Sep 2001 01:33:34 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/ssh-add.1 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.24 2001/04/10 09:13:21 itojun Exp $ +.\" $OpenBSD: ssh-add.1,v 1.35 2002/06/19 00:27:55 deraadt Exp $ .\" .\" -*- nroff -*- .\" @@ -42,22 +42,30 @@ .Os .Sh NAME .Nm ssh-add -.Nd adds RSA or DSA identities for the authentication agent +.Nd adds RSA or DSA identities to the authentication agent .Sh SYNOPSIS .Nm ssh-add -.Op Fl lLdD +.Op Fl lLdDxX +.Op Fl t Ar life .Op Ar +.Nm ssh-add +.Fl s Ar reader +.Nm ssh-add +.Fl e Ar reader .Sh DESCRIPTION .Nm adds RSA or DSA identities to the authentication agent, .Xr ssh-agent 1 . -When run without arguments, it adds the file +When run without arguments, it adds the files +.Pa $HOME/.ssh/id_rsa , +.Pa $HOME/.ssh/id_dsa +and .Pa $HOME/.ssh/identity . Alternative file names can be given on the command line. If any file requires a passphrase, .Nm asks for the passphrase from the user. -The Passphrase it is read from the user's tty. +The passphrase is read from the user's tty. .Nm retries the last passphrase if multiple identity files are given. .Pp @@ -76,26 +84,36 @@ Instead of adding the identity, removes the identity from the agent. .It Fl D Deletes all identities from the agent. +.It Fl x +Lock the agent with a password. +.It Fl X +Unlock the agent. +.It Fl t Ar life +Set a maximum lifetime when adding identities to an agent. +The lifetime may be specified in seconds or in a time format +specified in +.Xr sshd 8 . +.It Fl s Ar reader +Add key in smartcard +.Ar reader . +.It Fl e Ar reader +Remove key in smartcard +.Ar reader . .El .Sh FILES .Bl -tag -width Ds .It Pa $HOME/.ssh/identity Contains the protocol version 1 RSA authentication identity of the user. -This file should not be readable by anyone but the user. -Note that -.Nm -ignores this file if it is accessible by others. -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 -.Nm -when no other files have been specified. .It Pa $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. .It Pa $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. .El +.Pp +Identity files should not be readable by anyone but the user. +Note that +.Nm +ignores identity files if they are accessible by others. .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev "DISPLAY" and "SSH_ASKPASS" @@ -121,7 +139,15 @@ may be necessary to redirect the input from .Pa /dev/null to make this work.) +.It Ev SSH_AUTH_SOCK +Identifies the path of a unix-domain socket used to communicate with the +agent. .El +.Sh DIAGNOSTICS +Exit status is 0 on success, 1 if the specified command fails, +and 2 if +.Nm +is unable to contact the authentication agent. .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Index: src/crypto/openssh/ssh-add.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-add.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 ssh-add.c --- src/crypto/openssh/ssh-add.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/ssh-add.c 30 Jun 2002 11:38:01 -0000 @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation, - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,8 +35,7 @@ */ #include "includes.h" -RCSID("$FreeBSD: src/crypto/openssh/ssh-add.c,v 1.1.1.1.2.4 2001/09/28 01:33:35 green Exp $"); -RCSID("$OpenBSD: ssh-add.c,v 1.36 2001/04/18 21:57:42 markus Exp $"); +RCSID("$OpenBSD: ssh-add.c,v 1.61 2002/06/19 00:27:55 deraadt Exp $"); #include @@ -49,10 +48,31 @@ #include "authfile.h" #include "pathnames.h" #include "readpass.h" +#include "misc.h" + +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif + +/* argv0 */ +extern char *__progname; + +/* Default files to add */ +static char *default_files[] = { + _PATH_SSH_CLIENT_ID_RSA, + _PATH_SSH_CLIENT_ID_DSA, + _PATH_SSH_CLIENT_IDENTITY, + NULL +}; + +/* Default lifetime (0 == forever) */ +static int lifetime = 0; /* we keep a cache of one passphrases */ static char *pass = NULL; -void +static void clear_pass(void) { if (pass) { @@ -62,53 +82,61 @@ } } -void +static int delete_file(AuthenticationConnection *ac, const char *filename) { Key *public; char *comment = NULL; + int ret = -1; public = key_load_public(filename, &comment); if (public == NULL) { printf("Bad key file %s\n", filename); - return; + return -1; } - if (ssh_remove_identity(ac, public)) + if (ssh_remove_identity(ac, public)) { fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); - else + ret = 0; + } else fprintf(stderr, "Could not remove identity: %s\n", filename); + key_free(public); xfree(comment); + + return ret; } /* Send a request to remove all identities. */ -void +static int delete_all(AuthenticationConnection *ac) { - int success = 1; + int ret = -1; - if (!ssh_remove_all_identities(ac, 1)) - success = 0; + if (ssh_remove_all_identities(ac, 1)) + ret = 0; /* ignore error-code for ssh2 */ ssh_remove_all_identities(ac, 2); - if (success) + if (ret == 0) fprintf(stderr, "All identities removed.\n"); else fprintf(stderr, "Failed to remove all identities.\n"); + + return ret; } -void +static int add_file(AuthenticationConnection *ac, const char *filename) { struct stat st; Key *private; char *comment = NULL; char msg[1024]; + int ret = -1; if (stat(filename, &st) < 0) { perror(filename); - exit(1); + return -1; } /* At first, try empty passphrase */ private = key_load_private(filename, "", &comment); @@ -120,15 +148,14 @@ if (private == NULL) { /* clear passphrase since it did not work */ clear_pass(); - printf("Need passphrase for %.200s\n", filename); snprintf(msg, sizeof msg, "Enter passphrase for %.200s: ", comment); for (;;) { - pass = read_passphrase(msg, 1); + pass = read_passphrase(msg, RP_ALLOW_STDIN); if (strcmp(pass, "") == 0) { clear_pass(); xfree(comment); - return; + return -1; } private = key_load_private(filename, pass, &comment); if (private != NULL) @@ -137,15 +164,47 @@ strlcpy(msg, "Bad passphrase, try again: ", sizeof msg); } } - if (ssh_add_identity(ac, private, comment)) + + if (ssh_add_identity_constrained(ac, private, comment, lifetime)) { fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); - else + ret = 0; + if (lifetime != 0) + fprintf(stderr, + "Lifetime set to %d seconds\n", lifetime); + } else if (ssh_add_identity(ac, private, comment)) { + fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); + ret = 0; + } else { fprintf(stderr, "Could not add identity: %s\n", filename); + } + xfree(comment); key_free(private); + + return ret; +} + +static int +update_card(AuthenticationConnection *ac, int add, const char *id) +{ + char *pin; + + pin = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN); + if (pin == NULL) + return -1; + + if (ssh_update_card(ac, add, id, pin)) { + fprintf(stderr, "Card %s: %s\n", + add ? "added" : "removed", id); + return 0; + } else { + fprintf(stderr, "Could not %s card: %s\n", + add ? "add" : "remove", id); + return -1; + } } -void +static int list_identities(AuthenticationConnection *ac, int do_fp) { Key *key; @@ -155,8 +214,8 @@ for (version = 1; version <= 2; version++) { for (key = ssh_get_first_identity(ac, &comment, version); - key != NULL; - key = ssh_get_next_identity(ac, &comment, version)) { + key != NULL; + key = ssh_get_next_identity(ac, &comment, version)) { had_identities = 1; if (do_fp) { fp = key_fingerprint(key, SSH_FP_MD5, @@ -173,19 +232,84 @@ xfree(comment); } } - if (!had_identities) + if (!had_identities) { printf("The agent has no identities.\n"); + return -1; + } + return 0; +} + +static int +lock_agent(AuthenticationConnection *ac, int lock) +{ + char prompt[100], *p1, *p2; + int passok = 1, ret = -1; + + strlcpy(prompt, "Enter lock password: ", sizeof(prompt)); + p1 = read_passphrase(prompt, RP_ALLOW_STDIN); + if (lock) { + strlcpy(prompt, "Again: ", sizeof prompt); + p2 = read_passphrase(prompt, RP_ALLOW_STDIN); + if (strcmp(p1, p2) != 0) { + fprintf(stderr, "Passwords do not match.\n"); + passok = 0; + } + memset(p2, 0, strlen(p2)); + xfree(p2); + } + if (passok && ssh_lock_agent(ac, lock, p1)) { + fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un"); + ret = 0; + } else + fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un"); + memset(p1, 0, strlen(p1)); + xfree(p1); + return -1; +} + +static int +do_file(AuthenticationConnection *ac, int deleting, char *file) +{ + if (deleting) { + if (delete_file(ac, file) == -1) + return -1; + } else { + if (add_file(ac, file) == -1) + return -1; + } + return 0; +} + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s [options]\n", __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -l List fingerprints of all identities.\n"); + fprintf(stderr, " -L List public key parameters of all identities.\n"); + fprintf(stderr, " -d Delete identity.\n"); + fprintf(stderr, " -D Delete all identities.\n"); + fprintf(stderr, " -x Lock agent.\n"); + fprintf(stderr, " -x Unlock agent.\n"); + fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n"); +#ifdef SMARTCARD + fprintf(stderr, " -s reader Add key in smartcard reader.\n"); + fprintf(stderr, " -e reader Remove key in smartcard reader.\n"); +#endif } int main(int argc, char **argv) { + extern char *optarg; + extern int optind; AuthenticationConnection *ac = NULL; - struct passwd *pw; - char buf[1024]; - int no_files = 1; - int i; - int deleting = 0; + char *sc_reader_id = NULL; + int i, ch, deleting = 0, ret = 0; + + __progname = get_progname(argv[0]); + init_rng(); + seed_rng(); SSLeay_add_all_algorithms(); @@ -193,46 +317,91 @@ ac = ssh_get_authentication_connection(); if (ac == NULL) { fprintf(stderr, "Could not open a connection to your authentication agent.\n"); - exit(1); + exit(2); } - for (i = 1; i < argc; i++) { - if ((strcmp(argv[i], "-l") == 0) || - (strcmp(argv[i], "-L") == 0)) { - list_identities(ac, argv[i][1] == 'l' ? 1 : 0); - /* Don't default-add/delete if -l. */ - no_files = 0; - continue; - } - if (strcmp(argv[i], "-d") == 0) { + while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) { + switch (ch) { + case 'l': + case 'L': + if (list_identities(ac, ch == 'l' ? 1 : 0) == -1) + ret = 1; + goto done; + break; + case 'x': + case 'X': + if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1) + ret = 1; + goto done; + break; + case 'd': + deleting = 1; + break; + case 'D': + if (delete_all(ac) == -1) + ret = 1; + goto done; + break; + case 's': + sc_reader_id = optarg; + break; + case 'e': deleting = 1; - continue; + sc_reader_id = optarg; + break; + case 't': + if ((lifetime = convtime(optarg)) == -1) { + fprintf(stderr, "Invalid lifetime\n"); + ret = 1; + goto done; + } + break; + default: + usage(); + ret = 1; + goto done; } - if (strcmp(argv[i], "-D") == 0) { - delete_all(ac); - no_files = 0; - continue; - } - no_files = 0; - if (deleting) - delete_file(ac, argv[i]); - else - add_file(ac, argv[i]); - } - if (no_files) { - pw = getpwuid(getuid()); - if (!pw) { + } + argc -= optind; + argv += optind; + if (sc_reader_id != NULL) { + if (update_card(ac, !deleting, sc_reader_id) == -1) + ret = 1; + goto done; + } + if (argc == 0) { + char buf[MAXPATHLEN]; + struct passwd *pw; + struct stat st; + int count = 0; + + if ((pw = getpwuid(getuid())) == NULL) { fprintf(stderr, "No user found with uid %u\n", (u_int)getuid()); - ssh_close_authentication_connection(ac); - exit(1); + ret = 1; + goto done; + } + + for(i = 0; default_files[i]; i++) { + snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, + default_files[i]); + if (stat(buf, &st) < 0) + continue; + if (do_file(ac, deleting, buf) == -1) + ret = 1; + else + count++; + } + if (count == 0) + ret = 1; + } else { + for(i = 0; i < argc; i++) { + if (do_file(ac, deleting, argv[i]) == -1) + ret = 1; } - snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_CLIENT_IDENTITY); - if (deleting) - delete_file(ac, buf); - else - add_file(ac, buf); } clear_pass(); + +done: ssh_close_authentication_connection(ac); - exit(0); + return ret; } Index: src/crypto/openssh/ssh-agent.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-agent.1,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 ssh-agent.1 --- src/crypto/openssh/ssh-agent.1 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/ssh-agent.1 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.24 2001/04/10 09:13:21 itojun Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.35 2002/06/24 13:12:23 markus Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -42,11 +42,12 @@ .Nd authentication agent .Sh SYNOPSIS .Nm ssh-agent -.Ar command -.Ar args ... -.Nm ssh-agent +.Op Fl a Ar bind_address .Op Fl c Li | Fl s +.Op Fl d +.Op Ar command Op Ar args ... .Nm ssh-agent +.Op Fl c Li | Fl s .Fl k .Sh DESCRIPTION .Nm @@ -64,6 +65,11 @@ .Pp The options are as follows: .Bl -tag -width Ds +.It Fl a Ar bind_address +Bind the agent to the unix-domain socket +.Ar bind_address . +The default is +.Pa /tmp/ssh-XXXXXXXX/agent. . .It Fl c Generate C-shell commands on .Dv stdout . @@ -80,6 +86,10 @@ Kill the current agent (given by the .Ev SSH_AGENT_PID environment variable). +.It Fl d +Debug mode. When this option is specified +.Nm +will not fork. .El .Pp If a commandline is given, this is executed as a subprocess of the agent. @@ -90,9 +100,11 @@ .Xr ssh-add 1 . When executed without arguments, .Xr ssh-add 1 -adds the -.Pa $HOME/.ssh/identity -file. +adds the files +.Pa $HOME/.ssh/id_rsa , +.Pa $HOME/.ssh/id_dsa +and +.Pa $HOME/.ssh/identity . If the identity has a passphrase, .Xr ssh-add 1 asks for the passphrase (using a small X11 application if running @@ -112,9 +124,9 @@ identities anywhere in the network in a secure way. .Pp There are two main ways to get an agent setup: -Either you let the agent -start a new subcommand into which some environment variables are exported, or -you let the agent print the needed shell commands (either +Either the agent starts a new subcommand into which some environment +variables are exported, or the agent prints the needed shell commands +(either .Xr sh 1 or .Xr csh 1 @@ -123,8 +135,12 @@ .Xr ssh 1 looks at these variables and uses them to establish a connection to the agent. .Pp +The agent will never send a private key over its request channel. +Instead, operations that require a private key will be performed +by the agent, and the result will be returned to the requester. +This way, private keys are not exposed to clients using the agent. +.Pp A unix-domain socket is created -.Pq Pa /tmp/ssh-XXXXXXXX/agent. , and the name of this socket is stored in the .Ev SSH_AUTH_SOCK environment @@ -135,7 +151,7 @@ .Pp The .Ev SSH_AGENT_PID -environment variable holds the agent's PID. +environment variable holds the agent's process ID. .Pp The agent exits automatically when the command given on the command line terminates. @@ -143,20 +159,11 @@ .Bl -tag -width Ds .It Pa $HOME/.ssh/identity Contains the protocol version 1 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 -.Nm -but is normally added to the agent using -.Xr ssh-add 1 -at login time. .It Pa $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. .It Pa $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. -.It Pa /tmp/ssh-XXXXXXXX/agent. +.It Pa /tmp/ssh-XXXXXXXX/agent. Unix-domain sockets used to contain the connection to the authentication agent. These sockets should only be readable by the owner. Index: src/crypto/openssh/ssh-agent.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-agent.c,v retrieving revision 1.2.2.7 diff -u -u -r1.2.2.7 ssh-agent.c --- src/crypto/openssh/ssh-agent.c 28 Sep 2001 01:33:35 -0000 1.2.2.7 +++ src/crypto/openssh/ssh-agent.c 30 Jun 2002 11:38:01 -0000 @@ -1,5 +1,3 @@ -/* $OpenBSD: ssh-agent.c,v 1.54 2001/04/03 13:56:11 stevesk Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,8 +10,7 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * - * SSH2 implementation, - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,8 +34,9 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.54 2001/04/03 13:56:11 stevesk Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/ssh-agent.c,v 1.2.2.7 2001/09/28 01:33:35 green Exp $"); +#include "openbsd-compat/fake-queue.h" +RCSID("$OpenBSD: ssh-agent.c,v 1.97 2002/06/24 14:55:38 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/ssh-agent.c,v 1.15 2002/06/29 11:48:58 des Exp $"); #include #include @@ -48,36 +46,43 @@ #include "buffer.h" #include "bufaux.h" #include "xmalloc.h" -#include "packet.h" #include "getput.h" -#include "mpaux.h" #include "key.h" #include "authfd.h" -#include "cipher.h" -#include "kex.h" #include "compat.h" #include "log.h" +#ifdef SMARTCARD +#include "scard.h" +#endif + +typedef enum { + AUTH_UNUSED, + AUTH_SOCKET, + AUTH_CONNECTION +} sock_type; + typedef struct { int fd; - enum { - AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION - } type; + sock_type type; Buffer input; Buffer output; + Buffer request; } SocketEntry; u_int sockets_alloc = 0; SocketEntry *sockets = NULL; -typedef struct { +typedef struct identity { + TAILQ_ENTRY(identity) next; Key *key; char *comment; + u_int death; } Identity; typedef struct { int nentries; - Identity *identities; + TAILQ_HEAD(idqueue, identity) idlist; } Idtab; /* private key table, one per protocol version */ @@ -92,22 +97,29 @@ char socket_name[1024]; char socket_dir[1024]; -extern char *__progname; +/* locking */ +int locked = 0; +char *lock_passwd = NULL; -int prepare_select(fd_set **, fd_set **, int *); +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif -void +static void idtab_init(void) { int i; - for (i = 0; i <=2; i++){ - idtable[i].identities = NULL; + + for (i = 0; i <=2; i++) { + TAILQ_INIT(&idtable[i].idlist); idtable[i].nentries = 0; } } /* return private key table for requested protocol version */ -Idtab * +static Idtab * idtab_lookup(int version) { if (version < 1 || version > 2) @@ -115,36 +127,41 @@ return &idtable[version]; } +static void +free_identity(Identity *id) +{ + key_free(id->key); + xfree(id->comment); + xfree(id); +} + /* return matching private key for given public key */ -Key * -lookup_private_key(Key *key, int *idx, int version) +static Identity * +lookup_identity(Key *key, int version) { - int i; + Identity *id; + Idtab *tab = idtab_lookup(version); - for (i = 0; i < tab->nentries; i++) { - if (key_equal(key, tab->identities[i].key)) { - if (idx != NULL) - *idx = i; - return tab->identities[i].key; - } + TAILQ_FOREACH(id, &tab->idlist, next) { + if (key_equal(key, id->key)) + return (id); } - return NULL; + return (NULL); } /* send list of supported public keys to 'client' */ -void +static void process_request_identities(SocketEntry *e, int version) { Idtab *tab = idtab_lookup(version); + Identity *id; Buffer msg; - int i; buffer_init(&msg); buffer_put_char(&msg, (version == 1) ? SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); buffer_put_int(&msg, tab->nentries); - for (i = 0; i < tab->nentries; i++) { - Identity *id = &tab->identities[i]; + TAILQ_FOREACH(id, &tab->idlist, next) { if (id->key->type == KEY_RSA1) { buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); buffer_put_bignum(&msg, id->key->rsa->e); @@ -164,36 +181,39 @@ } /* ssh1 only */ -void +static void process_authentication_challenge1(SocketEntry *e) { - Key *key, *private; + u_char buf[32], mdbuf[16], session_id[16]; + u_int response_type; BIGNUM *challenge; + Identity *id; int i, len; Buffer msg; MD5_CTX md; - u_char buf[32], mdbuf[16], session_id[16]; - u_int response_type; + Key *key; buffer_init(&msg); key = key_new(KEY_RSA1); - challenge = BN_new(); + if ((challenge = BN_new()) == NULL) + fatal("process_authentication_challenge1: BN_new failed"); - buffer_get_int(&e->input); /* ignored */ - buffer_get_bignum(&e->input, key->rsa->e); - buffer_get_bignum(&e->input, key->rsa->n); - buffer_get_bignum(&e->input, challenge); + (void) buffer_get_int(&e->request); /* ignored */ + buffer_get_bignum(&e->request, key->rsa->e); + buffer_get_bignum(&e->request, key->rsa->n); + buffer_get_bignum(&e->request, challenge); /* Only protocol 1.1 is supported */ - if (buffer_len(&e->input) == 0) + if (buffer_len(&e->request) == 0) goto failure; - buffer_get(&e->input, (char *) session_id, 16); - response_type = buffer_get_int(&e->input); + buffer_get(&e->request, session_id, 16); + response_type = buffer_get_int(&e->request); if (response_type != 1) goto failure; - private = lookup_private_key(key, NULL, 1); - if (private != NULL) { + id = lookup_identity(key, 1); + if (id != NULL) { + Key *private = id->key; /* Decrypt the challenge using the private key. */ if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) goto failure; @@ -230,31 +250,30 @@ } /* ssh2 only */ -void +static void process_sign_request2(SocketEntry *e) { - extern int datafellows; - Key *key, *private; u_char *blob, *data, *signature = NULL; u_int blen, dlen, slen = 0; - int flags; + extern int datafellows; + int ok = -1, flags; Buffer msg; - int ok = -1; + Key *key; datafellows = 0; - blob = buffer_get_string(&e->input, &blen); - data = buffer_get_string(&e->input, &dlen); + blob = buffer_get_string(&e->request, &blen); + data = buffer_get_string(&e->request, &dlen); - flags = buffer_get_int(&e->input); + flags = buffer_get_int(&e->request); if (flags & SSH_AGENT_OLD_SIGNATURE) datafellows = SSH_BUG_SIGBLOB; key = key_from_blob(blob, blen); if (key != NULL) { - private = lookup_private_key(key, NULL, 2); - if (private != NULL) - ok = key_sign(private, &signature, &slen, data, dlen); + Identity *id = lookup_identity(key, 2); + if (id != NULL) + ok = key_sign(id->key, &signature, &slen, data, dlen); } key_free(key); buffer_init(&msg); @@ -275,36 +294,34 @@ } /* shared */ -void +static void process_remove_identity(SocketEntry *e, int version) { - Key *key = NULL, *private; - u_char *blob; - u_int blen; - u_int bits; + u_int blen, bits; int success = 0; + Key *key = NULL; + u_char *blob; - switch(version){ + switch (version) { case 1: key = key_new(KEY_RSA1); - bits = buffer_get_int(&e->input); - buffer_get_bignum(&e->input, key->rsa->e); - buffer_get_bignum(&e->input, key->rsa->n); + bits = buffer_get_int(&e->request); + buffer_get_bignum(&e->request, key->rsa->e); + buffer_get_bignum(&e->request, key->rsa->n); if (bits != key_size(key)) - log("Warning: identity keysize mismatch: actual %d, announced %d", + log("Warning: identity keysize mismatch: actual %u, announced %u", key_size(key), bits); break; case 2: - blob = buffer_get_string(&e->input, &blen); + blob = buffer_get_string(&e->request, &blen); key = key_from_blob(blob, blen); xfree(blob); break; } if (key != NULL) { - int idx; - private = lookup_private_key(key, &idx, version); - if (private != NULL) { + Identity *id = lookup_identity(key, version); + if (id != NULL) { /* * We have this key. Free the old key. Since we * don\'t want to leave empty slots in the middle of @@ -313,19 +330,12 @@ * of the array. */ Idtab *tab = idtab_lookup(version); - key_free(tab->identities[idx].key); - xfree(tab->identities[idx].comment); if (tab->nentries < 1) fatal("process_remove_identity: " "internal error: tab->nentries %d", tab->nentries); - if (idx != tab->nentries - 1) { - int i; - for (i = idx; i < tab->nentries - 1; i++) - tab->identities[i] = tab->identities[i+1]; - } - tab->identities[tab->nentries - 1].key = NULL; - tab->identities[tab->nentries - 1].comment = NULL; + TAILQ_REMOVE(&tab->idlist, id, next); + free_identity(id); tab->nentries--; success = 1; } @@ -336,16 +346,17 @@ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } -void +static void process_remove_all_identities(SocketEntry *e, int version) { - u_int i; Idtab *tab = idtab_lookup(version); + Identity *id; /* Loop over all identities and clear the keys. */ - for (i = 0; i < tab->nentries; i++) { - key_free(tab->identities[i].key); - xfree(tab->identities[i].comment); + for (id = TAILQ_FIRST(&tab->idlist); id; + id = TAILQ_FIRST(&tab->idlist)) { + TAILQ_REMOVE(&tab->idlist, id, next); + free_identity(id); } /* Mark that there are no identities. */ @@ -354,79 +365,105 @@ /* Send success. */ buffer_put_int(&e->output, 1); buffer_put_char(&e->output, SSH_AGENT_SUCCESS); - return; } -void +static void +reaper(void) +{ + u_int now = time(NULL); + Identity *id, *nxt; + int version; + Idtab *tab; + + for (version = 1; version < 3; version++) { + tab = idtab_lookup(version); + for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { + nxt = TAILQ_NEXT(id, next); + if (id->death != 0 && now >= id->death) { + TAILQ_REMOVE(&tab->idlist, id, next); + free_identity(id); + tab->nentries--; + } + } + } +} + +static void process_add_identity(SocketEntry *e, int version) { - Key *k = NULL; - char *type_name; - char *comment; - int type, success = 0; Idtab *tab = idtab_lookup(version); + int type, success = 0, death = 0; + char *type_name, *comment; + Key *k = NULL; switch (version) { case 1: k = key_new_private(KEY_RSA1); - buffer_get_int(&e->input); /* ignored */ - buffer_get_bignum(&e->input, k->rsa->n); - buffer_get_bignum(&e->input, k->rsa->e); - buffer_get_bignum(&e->input, k->rsa->d); - buffer_get_bignum(&e->input, k->rsa->iqmp); + (void) buffer_get_int(&e->request); /* ignored */ + buffer_get_bignum(&e->request, k->rsa->n); + buffer_get_bignum(&e->request, k->rsa->e); + buffer_get_bignum(&e->request, k->rsa->d); + buffer_get_bignum(&e->request, k->rsa->iqmp); /* SSH and SSL have p and q swapped */ - buffer_get_bignum(&e->input, k->rsa->q); /* p */ - buffer_get_bignum(&e->input, k->rsa->p); /* q */ + buffer_get_bignum(&e->request, k->rsa->q); /* p */ + buffer_get_bignum(&e->request, k->rsa->p); /* q */ /* Generate additional parameters */ - generate_additional_parameters(k->rsa); + rsa_generate_additional_parameters(k->rsa); break; case 2: - type_name = buffer_get_string(&e->input, NULL); + type_name = buffer_get_string(&e->request, NULL); type = key_type_from_name(type_name); xfree(type_name); - switch(type) { + switch (type) { case KEY_DSA: k = key_new_private(type); - buffer_get_bignum2(&e->input, k->dsa->p); - buffer_get_bignum2(&e->input, k->dsa->q); - buffer_get_bignum2(&e->input, k->dsa->g); - buffer_get_bignum2(&e->input, k->dsa->pub_key); - buffer_get_bignum2(&e->input, k->dsa->priv_key); + buffer_get_bignum2(&e->request, k->dsa->p); + buffer_get_bignum2(&e->request, k->dsa->q); + buffer_get_bignum2(&e->request, k->dsa->g); + buffer_get_bignum2(&e->request, k->dsa->pub_key); + buffer_get_bignum2(&e->request, k->dsa->priv_key); break; case KEY_RSA: k = key_new_private(type); - buffer_get_bignum2(&e->input, k->rsa->n); - buffer_get_bignum2(&e->input, k->rsa->e); - buffer_get_bignum2(&e->input, k->rsa->d); - buffer_get_bignum2(&e->input, k->rsa->iqmp); - buffer_get_bignum2(&e->input, k->rsa->p); - buffer_get_bignum2(&e->input, k->rsa->q); + buffer_get_bignum2(&e->request, k->rsa->n); + buffer_get_bignum2(&e->request, k->rsa->e); + buffer_get_bignum2(&e->request, k->rsa->d); + buffer_get_bignum2(&e->request, k->rsa->iqmp); + buffer_get_bignum2(&e->request, k->rsa->p); + buffer_get_bignum2(&e->request, k->rsa->q); /* Generate additional parameters */ - generate_additional_parameters(k->rsa); + rsa_generate_additional_parameters(k->rsa); break; default: - buffer_clear(&e->input); + buffer_clear(&e->request); goto send; } break; } - comment = buffer_get_string(&e->input, NULL); + comment = buffer_get_string(&e->request, NULL); if (k == NULL) { xfree(comment); goto send; } success = 1; - if (lookup_private_key(k, NULL, version) == NULL) { - if (tab->nentries == 0) - tab->identities = xmalloc(sizeof(Identity)); - else - tab->identities = xrealloc(tab->identities, - (tab->nentries + 1) * sizeof(Identity)); - tab->identities[tab->nentries].key = k; - tab->identities[tab->nentries].comment = comment; + while (buffer_len(&e->request)) { + switch (buffer_get_char(&e->request)) { + case SSH_AGENT_CONSTRAIN_LIFETIME: + death = time(NULL) + buffer_get_int(&e->request); + break; + default: + break; + } + } + if (lookup_identity(k, version) == NULL) { + Identity *id = xmalloc(sizeof(Identity)); + id->key = k; + id->comment = comment; + id->death = death; + TAILQ_INSERT_TAIL(&tab->idlist, id, next); /* Increment the number of identities. */ tab->nentries++; } else { @@ -439,30 +476,190 @@ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); } +/* XXX todo: encrypt sensitive data with passphrase */ +static void +process_lock_agent(SocketEntry *e, int lock) +{ + int success = 0; + char *passwd; + + passwd = buffer_get_string(&e->request, NULL); + if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { + locked = 0; + memset(lock_passwd, 0, strlen(lock_passwd)); + xfree(lock_passwd); + lock_passwd = NULL; + success = 1; + } else if (!locked && lock) { + locked = 1; + lock_passwd = xstrdup(passwd); + success = 1; + } + memset(passwd, 0, strlen(passwd)); + xfree(passwd); + + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, + success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); +} + +static void +no_identities(SocketEntry *e, u_int type) +{ + Buffer msg; + + buffer_init(&msg); + buffer_put_char(&msg, + (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? + SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); + buffer_put_int(&msg, 0); + buffer_put_int(&e->output, buffer_len(&msg)); + buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); + buffer_free(&msg); +} + +#ifdef SMARTCARD +static void +process_add_smartcard_key (SocketEntry *e) +{ + char *sc_reader_id = NULL, *pin; + int i, version, success = 0; + Key **keys, *k; + Identity *id; + Idtab *tab; + + sc_reader_id = buffer_get_string(&e->request, NULL); + pin = buffer_get_string(&e->request, NULL); + keys = sc_get_keys(sc_reader_id, pin); + xfree(sc_reader_id); + xfree(pin); + + if (keys == NULL || keys[0] == NULL) { + error("sc_get_keys failed"); + goto send; + } + for (i = 0; keys[i] != NULL; i++) { + k = keys[i]; + version = k->type == KEY_RSA1 ? 1 : 2; + tab = idtab_lookup(version); + if (lookup_identity(k, version) == NULL) { + id = xmalloc(sizeof(Identity)); + id->key = k; + id->comment = xstrdup("smartcard key"); + id->death = 0; + TAILQ_INSERT_TAIL(&tab->idlist, id, next); + tab->nentries++; + success = 1; + } else { + key_free(k); + } + keys[i] = NULL; + } + xfree(keys); +send: + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, + success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); +} + +static void +process_remove_smartcard_key(SocketEntry *e) +{ + char *sc_reader_id = NULL, *pin; + int i, version, success = 0; + Key **keys, *k = NULL; + Identity *id; + Idtab *tab; + + sc_reader_id = buffer_get_string(&e->request, NULL); + pin = buffer_get_string(&e->request, NULL); + keys = sc_get_keys(sc_reader_id, pin); + xfree(sc_reader_id); + xfree(pin); + + if (keys == NULL || keys[0] == NULL) { + error("sc_get_keys failed"); + goto send; + } + for (i = 0; keys[i] != NULL; i++) { + k = keys[i]; + version = k->type == KEY_RSA1 ? 1 : 2; + if ((id = lookup_identity(k, version)) != NULL) { + tab = idtab_lookup(version); + TAILQ_REMOVE(&tab->idlist, id, next); + tab->nentries--; + free_identity(id); + success = 1; + } + key_free(k); + keys[i] = NULL; + } + xfree(keys); +send: + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, + success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); +} +#endif /* SMARTCARD */ + /* dispatch incoming messages */ -void +static void process_message(SocketEntry *e) { - u_int msg_len; - u_int type; + u_int msg_len, type; u_char *cp; + + /* kill dead keys */ + reaper(); + if (buffer_len(&e->input) < 5) return; /* Incomplete message. */ - cp = (u_char *) buffer_ptr(&e->input); + cp = buffer_ptr(&e->input); msg_len = GET_32BIT(cp); if (msg_len > 256 * 1024) { shutdown(e->fd, SHUT_RDWR); close(e->fd); + e->fd = -1; e->type = AUTH_UNUSED; + buffer_free(&e->input); + buffer_free(&e->output); + buffer_free(&e->request); return; } if (buffer_len(&e->input) < msg_len + 4) return; + + /* move the current input to e->request */ buffer_consume(&e->input, 4); - type = buffer_get_char(&e->input); + buffer_clear(&e->request); + buffer_append(&e->request, buffer_ptr(&e->input), msg_len); + buffer_consume(&e->input, msg_len); + type = buffer_get_char(&e->request); + + /* check wheter agent is locked */ + if (locked && type != SSH_AGENTC_UNLOCK) { + buffer_clear(&e->request); + switch (type) { + case SSH_AGENTC_REQUEST_RSA_IDENTITIES: + case SSH2_AGENTC_REQUEST_IDENTITIES: + /* send empty lists */ + no_identities(e, type); + break; + default: + /* send a fail message for all other request types */ + buffer_put_int(&e->output, 1); + buffer_put_char(&e->output, SSH_AGENT_FAILURE); + } + return; + } + debug("type %d", type); switch (type) { + case SSH_AGENTC_LOCK: + case SSH_AGENTC_UNLOCK: + process_lock_agent(e, type == SSH_AGENTC_LOCK); + break; /* ssh1 */ case SSH_AGENTC_RSA_CHALLENGE: process_authentication_challenge1(e); @@ -471,6 +668,7 @@ process_request_identities(e, 1); break; case SSH_AGENTC_ADD_RSA_IDENTITY: + case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED: process_add_identity(e, 1); break; case SSH_AGENTC_REMOVE_RSA_IDENTITY: @@ -487,6 +685,7 @@ process_request_identities(e, 2); break; case SSH2_AGENTC_ADD_IDENTITY: + case SSH2_AGENTC_ADD_ID_CONSTRAINED: process_add_identity(e, 2); break; case SSH2_AGENTC_REMOVE_IDENTITY: @@ -495,20 +694,29 @@ case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: process_remove_all_identities(e, 2); break; +#ifdef SMARTCARD + case SSH_AGENTC_ADD_SMARTCARD_KEY: + process_add_smartcard_key(e); + break; + case SSH_AGENTC_REMOVE_SMARTCARD_KEY: + process_remove_smartcard_key(e); + break; +#endif /* SMARTCARD */ default: /* Unknown message. Respond with failure. */ error("Unknown message %d", type); - buffer_clear(&e->input); + buffer_clear(&e->request); buffer_put_int(&e->output, 1); buffer_put_char(&e->output, SSH_AGENT_FAILURE); break; } } -void -new_socket(int type, int fd) +static void +new_socket(sock_type type, int fd) { u_int i, old_alloc; + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) error("fcntl O_NONBLOCK: %s", strerror(errno)); @@ -521,6 +729,7 @@ sockets[i].type = type; buffer_init(&sockets[i].input); buffer_init(&sockets[i].output); + buffer_init(&sockets[i].request); return; } old_alloc = sockets_alloc; @@ -535,10 +744,11 @@ sockets[old_alloc].fd = fd; buffer_init(&sockets[old_alloc].input); buffer_init(&sockets[old_alloc].output); + buffer_init(&sockets[old_alloc].request); } -int -prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl) +static int +prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp) { u_int i, sz; int n = 0; @@ -558,15 +768,18 @@ } sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); - if (*fdrp == NULL || n > *fdl) { + if (*fdrp == NULL || sz > *nallocp) { if (*fdrp) xfree(*fdrp); if (*fdwp) xfree(*fdwp); *fdrp = xmalloc(sz); *fdwp = xmalloc(sz); - *fdl = n; + *nallocp = sz; } + if (n < *fdl) + debug("XXX shrink: %d < %d", n, *fdl); + *fdl = n; memset(*fdrp, 0, sz); memset(*fdwp, 0, sz); @@ -585,14 +798,14 @@ return (1); } -void +static void after_select(fd_set *readset, fd_set *writeset) { - u_int i; - int len, sock; + struct sockaddr_un sunaddr; socklen_t slen; char buf[1024]; - struct sockaddr_un sunaddr; + int len, sock; + u_int i; for (i = 0; i < sockets_alloc; i++) switch (sockets[i].type) { @@ -604,7 +817,8 @@ sock = accept(sockets[i].fd, (struct sockaddr *) &sunaddr, &slen); if (sock < 0) { - perror("accept from AUTH_SOCKET"); + error("accept from AUTH_SOCKET: %s", + strerror(errno)); break; } new_socket(AUTH_CONNECTION, sock); @@ -625,9 +839,11 @@ if (len <= 0) { shutdown(sockets[i].fd, SHUT_RDWR); close(sockets[i].fd); + sockets[i].fd = -1; sockets[i].type = AUTH_UNUSED; buffer_free(&sockets[i].input); buffer_free(&sockets[i].output); + buffer_free(&sockets[i].request); break; } buffer_consume(&sockets[i].output, len); @@ -643,9 +859,11 @@ if (len <= 0) { shutdown(sockets[i].fd, SHUT_RDWR); close(sockets[i].fd); + sockets[i].fd = -1; sockets[i].type = AUTH_UNUSED; buffer_free(&sockets[i].input); buffer_free(&sockets[i].output); + buffer_free(&sockets[i].request); break; } buffer_append(&sockets[i].input, buf, len); @@ -657,22 +875,8 @@ } } -void -check_parent_exists(int sig) -{ - int save_errno = errno; - - if (parent_pid != -1 && kill(parent_pid, 0) < 0) { - /* printf("Parent has died - Authentication agent exiting.\n"); */ - exit(1); - } - signal(SIGALRM, check_parent_exists); - alarm(10); - errno = save_errno; -} - -void -cleanup_socket(void) +static void +cleanup_socket(void *p) { if (socket_name[0]) unlink(socket_name); @@ -680,43 +884,73 @@ rmdir(socket_dir); } -void +static void cleanup_exit(int i) { - cleanup_socket(); + cleanup_socket(NULL); exit(i); } -void +static void cleanup_handler(int sig) { - cleanup_socket(); + cleanup_socket(NULL); _exit(2); } -void +static void +check_parent_exists(int sig) +{ + int save_errno = errno; + + if (parent_pid != -1 && kill(parent_pid, 0) < 0) { + /* printf("Parent has died - Authentication agent exiting.\n"); */ + cleanup_handler(sig); /* safe */ + } + signal(SIGALRM, check_parent_exists); + alarm(10); + errno = save_errno; +} + +static void usage(void) { - fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); - fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", + fprintf(stderr, "Usage: %s [options] [command [args ...]]\n", __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); + fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n"); + fprintf(stderr, " -k Kill the current agent.\n"); + fprintf(stderr, " -d Debug mode.\n"); + fprintf(stderr, " -a socket Bind agent socket to given name.\n"); exit(1); } int main(int ac, char **av) { - int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; + int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc; + char *shell, *format, *pidstr, *agentsocket = NULL; + fd_set *readsetp = NULL, *writesetp = NULL; struct sockaddr_un sunaddr; +#ifdef HAVE_SETRLIMIT struct rlimit rlim; - pid_t pid; - char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; +#endif +#ifdef HAVE_CYGWIN + int prev_mask; +#endif extern int optind; - fd_set *readsetp = NULL, *writesetp = NULL; + extern char *optarg; + pid_t pid; + char pidstrbuf[1 + 3 * sizeof pid]; SSLeay_add_all_algorithms(); - while ((ch = getopt(ac, av, "cks")) != -1) { + __progname = get_progname(av[0]); + init_rng(); + seed_rng(); + + while ((ch = getopt(ac, av, "cdksa:")) != -1) { switch (ch) { case 'c': if (s_flag) @@ -731,6 +965,14 @@ usage(); s_flag++; break; + case 'd': + if (d_flag) + usage(); + d_flag++; + break; + case 'a': + agentsocket = optarg; + break; default: usage(); } @@ -738,10 +980,10 @@ ac -= optind; av += optind; - if (ac > 0 && (c_flag || k_flag || s_flag)) + if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) usage(); - if (ac == 0 && !c_flag && !k_flag && !s_flag) { + if (ac == 0 && !c_flag && !s_flag) { shell = getenv("SHELL"); if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) c_flag = 1; @@ -766,19 +1008,25 @@ format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME); - printf("echo Agent pid %d killed;\n", pid); + printf("echo Agent pid %ld killed;\n", (long)pid); exit(0); } parent_pid = getpid(); - /* Create private directory for agent socket */ - strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir); - if (mkdtemp(socket_dir) == NULL) { - perror("mkdtemp: private socket dir"); - exit(1); + if (agentsocket == NULL) { + /* Create private directory for agent socket */ + strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir); + if (mkdtemp(socket_dir) == NULL) { + perror("mkdtemp: private socket dir"); + exit(1); + } + snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, + (long)parent_pid); + } else { + /* Try to use specified agent socket */ + socket_dir[0] = '\0'; + strlcpy(socket_name, agentsocket, sizeof socket_name); } - snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, - parent_pid); /* * Create socket early so it will exist before command gets run from @@ -792,11 +1040,19 @@ memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); - sunaddr.sun_len = SUN_LEN(&sunaddr) + 1; - if (bind(sock, (struct sockaddr *)&sunaddr, sunaddr.sun_len) < 0) { +#ifdef HAVE_CYGWIN + prev_mask = umask(0177); +#endif + if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { perror("bind"); +#ifdef HAVE_CYGWIN + umask(prev_mask); +#endif cleanup_exit(1); } +#ifdef HAVE_CYGWIN + umask(prev_mask); +#endif if (listen(sock, 5) < 0) { perror("listen"); cleanup_exit(1); @@ -806,21 +1062,29 @@ * Fork, and have the parent execute the command, if any, or present * the socket data. The child continues as the authentication agent. */ + if (d_flag) { + log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); + format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; + printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, + SSH_AUTHSOCKET_ENV_NAME); + printf("echo Agent pid %ld;\n", (long)parent_pid); + goto skip; + } pid = fork(); if (pid == -1) { perror("fork"); - exit(1); + cleanup_exit(1); } if (pid != 0) { /* Parent - execute the given command. */ close(sock); - snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid); + snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); if (ac == 0) { format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, SSH_AGENTPID_ENV_NAME); - printf("echo Agent pid %d;\n", pid); + printf("echo Agent pid %ld;\n", (long)pid); exit(0); } if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || @@ -832,40 +1096,49 @@ perror(av[0]); exit(1); } + /* child */ + log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); + + if (setsid() == -1) { + error("setsid: %s", strerror(errno)); + cleanup_exit(1); + } + + (void)chdir("/"); close(0); close(1); close(2); +#ifdef HAVE_SETRLIMIT /* deny core dumps, since memory contains unencrypted private keys */ rlim.rlim_cur = rlim.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &rlim) < 0) { - perror("setrlimit rlimit_core failed"); - cleanup_exit(1); - } - if (setsid() == -1) { - perror("setsid"); - cleanup_exit(1); - } - if (atexit(cleanup_socket) < 0) { - perror("atexit"); + error("setrlimit RLIMIT_CORE: %s", strerror(errno)); cleanup_exit(1); } +#endif + +skip: + fatal_add_cleanup(cleanup_socket, NULL); new_socket(AUTH_SOCKET, sock); if (ac > 0) { signal(SIGALRM, check_parent_exists); alarm(10); } idtab_init(); - signal(SIGINT, SIG_IGN); + if (!d_flag) + signal(SIGINT, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, cleanup_handler); signal(SIGTERM, cleanup_handler); + nalloc = 0; + while (1) { - prepare_select(&readsetp, &writesetp, &max_fd); + prepare_select(&readsetp, &writesetp, &max_fd, &nalloc); if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) { if (errno == EINTR) continue; - exit(1); + fatal("select: %s", strerror(errno)); } after_select(readsetp, writesetp); } Index: src/crypto/openssh/ssh-dss.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-dss.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh-dss.c --- src/crypto/openssh/ssh-dss.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh-dss.c 30 Jun 2002 11:38:01 -0000 @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-dss.c,v 1.6 2001/02/08 19:30:52 itojun Exp $"); +RCSID("$OpenBSD: ssh-dss.c,v 1.15 2002/06/23 03:30:17 deraadt Exp $"); #include #include @@ -40,55 +40,45 @@ #define SIGBLOB_LEN (2*INTBLOB_LEN) int -ssh_dss_sign( - Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen) +ssh_dss_sign(Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { - u_char *digest; - u_char *ret; DSA_SIG *sig; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; - u_int rlen; - u_int slen; - u_int len, dlen; - u_char sigblob[SIGBLOB_LEN]; + u_char *ret, digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; + u_int rlen, slen, len, dlen; Buffer b; if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { error("ssh_dss_sign: no DSA key"); return -1; } - dlen = evp_md->md_size; - digest = xmalloc(dlen); EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, NULL); + EVP_DigestFinal(&md, digest, &dlen); sig = DSA_do_sign(digest, dlen, key->dsa); + memset(digest, 'd', sizeof(digest)); + if (sig == NULL) { - fatal("ssh_dss_sign: cannot sign"); + error("ssh_dss_sign: sign failed"); + return -1; } - memset(digest, 0, dlen); - xfree(digest); rlen = BN_num_bytes(sig->r); slen = BN_num_bytes(sig->s); if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { - error("bad sig size %d %d", rlen, slen); + error("bad sig size %u %u", rlen, slen); DSA_SIG_free(sig); return -1; } - debug("sig size %d %d", rlen, slen); - memset(sigblob, 0, SIGBLOB_LEN); BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); DSA_SIG_free(sig); if (datafellows & SSH_BUG_SIGBLOB) { - debug("datafellows"); ret = xmalloc(SIGBLOB_LEN); memcpy(ret, sigblob, SIGBLOB_LEN); if (lenp != NULL) @@ -112,39 +102,22 @@ return 0; } int -ssh_dss_verify( - Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen) +ssh_dss_verify(Key *key, u_char *signature, u_int signaturelen, + u_char *data, u_int datalen) { - Buffer b; - u_char *digest; DSA_SIG *sig; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; - u_char *sigblob; - char *txt; + u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen; - int rlen; - int ret; + int rlen, ret; + Buffer b; if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { error("ssh_dss_verify: no DSA key"); return -1; } - if (!(datafellows & SSH_BUG_SIGBLOB) && - signaturelen == SIGBLOB_LEN) { - datafellows |= ~SSH_BUG_SIGBLOB; - log("autodetect SSH_BUG_SIGBLOB"); - } else if ((datafellows & SSH_BUG_SIGBLOB) && - signaturelen != SIGBLOB_LEN) { - log("autoremove SSH_BUG_SIGBLOB"); - datafellows &= ~SSH_BUG_SIGBLOB; - } - - debug("len %d datafellows %d", signaturelen, datafellows); - /* fetch signature */ if (datafellows & SSH_BUG_SIGBLOB) { sigblob = signature; @@ -153,32 +126,37 @@ /* ietf-drafts */ char *ktype; buffer_init(&b); - buffer_append(&b, (char *) signature, signaturelen); + buffer_append(&b, signature, signaturelen); ktype = buffer_get_string(&b, NULL); if (strcmp("ssh-dss", ktype) != 0) { error("ssh_dss_verify: cannot handle type %s", ktype); buffer_free(&b); + xfree(ktype); return -1; } - sigblob = (u_char *)buffer_get_string(&b, &len); + xfree(ktype); + sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); - if(rlen != 0) { - error("remaining bytes in signature %d", rlen); - buffer_free(&b); + buffer_free(&b); + if (rlen != 0) { + error("ssh_dss_verify: " + "remaining bytes in signature %d", rlen); + xfree(sigblob); return -1; } - buffer_free(&b); - xfree(ktype); } if (len != SIGBLOB_LEN) { - fatal("bad sigbloblen %d != SIGBLOB_LEN", len); + fatal("bad sigbloblen %u != SIGBLOB_LEN", len); } /* parse signature */ - sig = DSA_SIG_new(); - sig->r = BN_new(); - sig->s = BN_new(); + if ((sig = DSA_SIG_new()) == NULL) + fatal("ssh_dss_verify: DSA_SIG_new failed"); + if ((sig->r = BN_new()) == NULL) + fatal("ssh_dss_verify: BN_new failed"); + if ((sig->s = BN_new()) == NULL) + fatal("ssh_dss_verify: BN_new failed"); BN_bin2bn(sigblob, INTBLOB_LEN, sig->r); BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s); @@ -188,30 +166,16 @@ } /* sha1 the data */ - dlen = evp_md->md_size; - digest = xmalloc(dlen); EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, NULL); + EVP_DigestFinal(&md, digest, &dlen); ret = DSA_do_verify(digest, dlen, sig, key->dsa); + memset(digest, 'd', sizeof(digest)); - memset(digest, 0, dlen); - xfree(digest); DSA_SIG_free(sig); - switch (ret) { - case 1: - txt = "correct"; - break; - case 0: - txt = "incorrect"; - break; - case -1: - default: - txt = "error"; - break; - } - debug("ssh_dss_verify: signature %s", txt); + debug("ssh_dss_verify: signature %s", + ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); return ret; } Index: src/crypto/openssh/ssh-dss.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-dss.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh-dss.h --- src/crypto/openssh/ssh-dss.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh-dss.h 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.h,v 1.3 2001/01/29 01:58:18 niklas Exp $ */ +/* $OpenBSD: ssh-dss.h,v 1.6 2002/02/24 19:14:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -26,16 +26,7 @@ #ifndef DSA_H #define DSA_H -int -ssh_dss_sign( - Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen); - -int -ssh_dss_verify( - Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen); +int ssh_dss_sign(Key *, u_char **, u_int *, u_char *, u_int); +int ssh_dss_verify(Key *, u_char *, u_int, u_char *, u_int); #endif Index: src/crypto/openssh/ssh-keygen.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-keygen.1,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 ssh-keygen.1 --- src/crypto/openssh/ssh-keygen.1 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/ssh-keygen.1 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.40 2001/04/23 21:57:07 markus Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.54 2002/06/19 00:27:55 deraadt Exp $ .\" .\" -*- nroff -*- .\" @@ -47,7 +47,7 @@ .Nm ssh-keygen .Op Fl q .Op Fl b Ar bits -.Op Fl t Ar type +.Fl t Ar type .Op Fl N Ar new_passphrase .Op Fl C Ar comment .Op Fl f Ar output_keyfile @@ -76,15 +76,21 @@ .Nm ssh-keygen .Fl B .Op Fl f Ar input_keyfile +.Nm ssh-keygen +.Fl D Ar reader +.Nm ssh-keygen +.Fl U Ar reader +.Op Fl f Ar input_keyfile .Sh DESCRIPTION .Nm generates, manages and converts authentication keys for .Xr ssh 1 . .Nm -defaults to generating a RSA1 key for use by SSH protocol version 1. -specifying the +can create RSA keys for use by SSH protocol version 1 and RSA or DSA +keys for use by SSH protocol version 2. The type of key to be generated +is specified with the .Fl t -option allows you to create a key for use by SSH protocol version 2. +option. .Pp Normally each user wishing to use SSH with RSA or DSA authentication runs this once to create the authentication @@ -106,17 +112,21 @@ The passphrase may be empty to indicate no passphrase (host keys must have an empty passphrase), or it may be a string of arbitrary length. -Good passphrases are 10-30 characters long and are +A passphrase is similar to a password, except it can be a phrase with a +series of words, punctuation, numbers, whitespace, or any string of +characters you want. +Good passphrases are 10-30 characters long, are not simple sentences or otherwise easily guessable (English -prose has only 1-2 bits of entropy per word, and provides very bad -passphrases). +prose has only 1-2 bits of entropy per character, and provides very bad +passphrases), and contain a mix of upper and lowercase letters, +numbers, and non-alphanumeric characters. The passphrase can be changed later by using the .Fl p option. .Pp 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 +lost or forgotten, a new key must be generated and copied to the corresponding public key to other machines. .Pp For RSA1 keys, @@ -142,8 +152,9 @@ The default is 1024 bits. .It Fl c Requests changing the comment in the private and public key files. +This operation is only supported for RSA1 keys. The program will prompt for the file containing the private keys, for -passphrase if the key has one, and for the new comment. +the passphrase if the key has one, and for the new comment. .It Fl e This option will read a private or public OpenSSH key file and print the key in a @@ -151,7 +162,7 @@ to stdout. This option allows exporting keys for use by several commercial SSH implementations. -.It Fl f +.It Fl f Ar filename Specifies the filename of the key file. .It Fl i This option will read an unencrypted private (or public) key file @@ -163,7 +174,11 @@ This option allows importing keys from several commercial SSH implementations. .It Fl l -Show fingerprint of specified private or public key file. +Show fingerprint of specified public key file. +Private RSA1 keys are also supported. +For RSA and DSA keys +.Nm +tries to find the matching public key file and prints its fingerprint. .It Fl p Requests changing the passphrase of a private key file instead of creating a new private key. @@ -188,16 +203,20 @@ or .Dq dsa for protocol version 2. -The default is -.Dq rsa1 . .It Fl B Show the bubblebabble digest of specified private or public key file. .It Fl C Ar comment Provides the new comment. +.It Fl D Ar reader +Download the RSA public key stored in the smartcard in +.Ar reader . .It Fl N Ar new_passphrase Provides the new passphrase. .It Fl P Ar passphrase Provides the (old) passphrase. +.It Fl U Ar reader +Upload an existing RSA private key into the smartcard in +.Ar reader . .El .Sh FILES .Bl -tag -width Ds @@ -210,14 +229,14 @@ This file is not automatically accessed by .Nm but it is offered as the default file for the private key. -.Xr sshd 8 +.Xr ssh 1 will read this file when a login attempt is made. .It Pa $HOME/.ssh/identity.pub Contains the protocol version 1 RSA public key for authentication. The contents of this file should be added to .Pa $HOME/.ssh/authorized_keys on all machines -where you wish to log in using RSA authentication. +where the user wishes to log in using RSA authentication. There is no need to keep the contents of this file secret. .It Pa $HOME/.ssh/id_dsa Contains the protocol version 2 DSA authentication identity of the user. @@ -228,14 +247,14 @@ This file is not automatically accessed by .Nm but it is offered as the default file for the private key. -.Xr sshd 8 +.Xr ssh 1 will read this file when a login attempt is made. .It Pa $HOME/.ssh/id_dsa.pub Contains the protocol version 2 DSA public key for authentication. The contents of this file should be added to -.Pa $HOME/.ssh/authorized_keys2 +.Pa $HOME/.ssh/authorized_keys on all machines -where you wish to log in using public key authentication. +where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. .It Pa $HOME/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. @@ -246,14 +265,14 @@ This file is not automatically accessed by .Nm but it is offered as the default file for the private key. -.Xr sshd 8 +.Xr ssh 1 will read this file when a login attempt is made. .It Pa $HOME/.ssh/id_rsa.pub Contains the protocol version 2 RSA public key for authentication. The contents of this file should be added to -.Pa $HOME/.ssh/authorized_keys2 +.Pa $HOME/.ssh/authorized_keys on all machines -where you wish to log in using public key authentication. +where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. .El .Sh AUTHORS Index: src/crypto/openssh/ssh-keygen.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-keygen.c,v retrieving revision 1.1.1.1.2.4 diff -u -u -r1.1.1.1.2.4 ssh-keygen.c --- src/crypto/openssh/ssh-keygen.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.4 +++ src/crypto/openssh/ssh-keygen.c 30 Jun 2002 11:38:01 -0000 @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keygen.c,v 1.60 2001/04/23 22:14:13 markus Exp $"); +RCSID("$OpenBSD: ssh-keygen.c,v 1.101 2002/06/23 09:39:55 deraadt Exp $"); #include #include @@ -28,6 +28,10 @@ #include "log.h" #include "readpass.h" +#ifdef SMARTCARD +#include "scard.h" +#endif + /* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ int bits = 1024; @@ -67,35 +71,42 @@ int convert_from_ssh2 = 0; int print_public = 0; -/* default to RSA for SSH-1 */ -char *key_type_name = "rsa1"; +char *key_type_name = NULL; /* argv0 */ +#ifdef HAVE___PROGNAME extern char *__progname; +#else +char *__progname; +#endif char hostname[MAXHOSTNAMELEN]; -void +static void ask_filename(struct passwd *pw, const char *prompt) { char buf[1024]; char *name = NULL; - switch (key_type_from_name(key_type_name)) { - case KEY_RSA1: - name = _PATH_SSH_CLIENT_IDENTITY; - break; - case KEY_DSA: - name = _PATH_SSH_CLIENT_ID_DSA; - break; - case KEY_RSA: + if (key_type_name == NULL) name = _PATH_SSH_CLIENT_ID_RSA; - break; - default: - fprintf(stderr, "bad key type"); - exit(1); - break; - } + else + switch (key_type_from_name(key_type_name)) { + case KEY_RSA1: + name = _PATH_SSH_CLIENT_IDENTITY; + break; + case KEY_DSA: + name = _PATH_SSH_CLIENT_ID_DSA; + break; + case KEY_RSA: + name = _PATH_SSH_CLIENT_ID_RSA; + break; + default: + fprintf(stderr, "bad key type"); + exit(1); + break; + } + snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); fprintf(stderr, "%s (%s): ", prompt, identity_file); fflush(stderr); @@ -108,15 +119,19 @@ have_identity = 1; } -Key * -try_load_pem_key(char *filename) +static Key * +load_identity(char *filename) { char *pass; Key *prv; prv = key_load_private(filename, "", NULL); if (prv == NULL) { - pass = read_passphrase("Enter passphrase: ", 1); + if (identity_passphrase) + pass = xstrdup(identity_passphrase); + else + pass = read_passphrase("Enter passphrase: ", + RP_ALLOW_STDIN); prv = key_load_private(filename, pass, NULL); memset(pass, 0, strlen(pass)); xfree(pass); @@ -125,15 +140,15 @@ } #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----" -#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----" +#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----" #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb -void +static void do_convert_to_ssh2(struct passwd *pw) { Key *k; - int len; + u_int len; u_char *blob; struct stat st; @@ -144,15 +159,18 @@ exit(1); } if ((k = key_load_public(identity_file, NULL)) == NULL) { - if ((k = try_load_pem_key(identity_file)) == NULL) { + if ((k = load_identity(identity_file)) == NULL) { fprintf(stderr, "load failed\n"); exit(1); } } - key_to_blob(k, &blob, &len); + if (key_to_blob(k, &blob, &len) <= 0) { + fprintf(stderr, "key_to_blob failed\n"); + exit(1); + } fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); fprintf(stdout, - "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n", + "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n", key_size(k), key_type(k), pw->pw_name, hostname); dump_base64(stdout, blob, len); @@ -162,7 +180,7 @@ exit(0); } -void +static void buffer_get_bignum_bits(Buffer *b, BIGNUM *value) { int bits = buffer_get_int(b); @@ -171,17 +189,20 @@ if (buffer_len(b) < bytes) fatal("buffer_get_bignum_bits: input buffer too small: " "need %d have %d", bytes, buffer_len(b)); - BN_bin2bn((u_char *)buffer_ptr(b), bytes, value); + BN_bin2bn(buffer_ptr(b), bytes, value); buffer_consume(b, bytes); } -Key * -do_convert_private_ssh2_from_blob(char *blob, int blen) +static Key * +do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) { Buffer b; Key *key = NULL; - int ignore, magic, rlen, ktype; char *type, *cipher; + u_char *sig, data[] = "abcde12345"; + int magic, rlen, ktype, i1, i2, i3, i4; + u_int slen; + u_long e; buffer_init(&b); buffer_append(&b, blob, blen); @@ -192,13 +213,13 @@ buffer_free(&b); return NULL; } - ignore = buffer_get_int(&b); + i1 = buffer_get_int(&b); type = buffer_get_string(&b, NULL); cipher = buffer_get_string(&b, NULL); - ignore = buffer_get_int(&b); - ignore = buffer_get_int(&b); - ignore = buffer_get_int(&b); - + i2 = buffer_get_int(&b); + i3 = buffer_get_int(&b); + i4 = buffer_get_int(&b); + debug("ignore (%d %d %d %d)", i1,i2,i3,i4); if (strcmp(cipher, "none") != 0) { error("unsupported cipher %s", cipher); xfree(cipher); @@ -228,7 +249,17 @@ buffer_get_bignum_bits(&b, key->dsa->priv_key); break; case KEY_RSA: - if (!BN_set_word(key->rsa->e, (u_long) buffer_get_char(&b))) { + e = buffer_get_char(&b); + debug("e %lx", e); + if (e < 30) { + e <<= 8; + e += buffer_get_char(&b); + debug("e %lx", e); + e <<= 8; + e += buffer_get_char(&b); + debug("e %lx", e); + } + if (!BN_set_word(key->rsa->e, e)) { buffer_free(&b); key_free(key); return NULL; @@ -238,34 +269,30 @@ buffer_get_bignum_bits(&b, key->rsa->iqmp); buffer_get_bignum_bits(&b, key->rsa->q); buffer_get_bignum_bits(&b, key->rsa->p); - generate_additional_parameters(key->rsa); + rsa_generate_additional_parameters(key->rsa); break; } rlen = buffer_len(&b); - if(rlen != 0) + if (rlen != 0) error("do_convert_private_ssh2_from_blob: " "remaining bytes in key blob %d", rlen); buffer_free(&b); -#ifdef DEBUG_PK - { - u_int slen; - u_char *sig, data[10] = "abcde12345"; - - key_sign(key, &sig, &slen, data, sizeof data); - key_verify(key, sig, slen, data, sizeof data); - xfree(sig); - } -#endif + + /* try the key */ + key_sign(key, &sig, &slen, data, sizeof(data)); + key_verify(key, sig, slen, data, sizeof(data)); + xfree(sig); return key; } -void +static void do_convert_from_ssh2(struct passwd *pw) { Key *k; int blen; + u_int len; char line[1024], *p; - char blob[8096]; + u_char blob[8096]; char encoded[8096]; struct stat st; int escaped = 0, private = 0, ok; @@ -294,6 +321,9 @@ strstr(line, ": ") != NULL) { if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) private = 1; + if (strstr(line, " END ") != NULL) { + break; + } /* fprintf(stderr, "ignore: %s", line); */ continue; } @@ -305,7 +335,13 @@ *p = '\0'; strlcat(encoded, line, sizeof(encoded)); } - blen = uudecode(encoded, (u_char *)blob, sizeof(blob)); + len = strlen(encoded); + if (((len % 4) == 3) && + (encoded[len-1] == '=') && + (encoded[len-2] == '=') && + (encoded[len-3] == '=')) + encoded[len-3] = '\0'; + blen = uudecode(encoded, blob, sizeof(blob)); if (blen < 0) { fprintf(stderr, "uudecode failed.\n"); exit(1); @@ -327,12 +363,13 @@ exit(1); } key_free(k); - fprintf(stdout, "\n"); + if (!private) + fprintf(stdout, "\n"); fclose(fp); exit(0); } -void +static void do_print_public(struct passwd *pw) { Key *prv; @@ -344,7 +381,7 @@ perror(identity_file); exit(1); } - prv = try_load_pem_key(identity_file); + prv = load_identity(identity_file); if (prv == NULL) { fprintf(stderr, "load failed\n"); exit(1); @@ -356,13 +393,61 @@ exit(0); } -void +#ifdef SMARTCARD +static void +do_upload(struct passwd *pw, const char *sc_reader_id) +{ + Key *prv = NULL; + struct stat st; + int ret; + + if (!have_identity) + ask_filename(pw, "Enter file in which the key is"); + if (stat(identity_file, &st) < 0) { + perror(identity_file); + exit(1); + } + prv = load_identity(identity_file); + if (prv == NULL) { + error("load failed"); + exit(1); + } + ret = sc_put_key(prv, sc_reader_id); + key_free(prv); + if (ret < 0) + exit(1); + log("loading key done"); + exit(0); +} + +static void +do_download(struct passwd *pw, const char *sc_reader_id) +{ + Key **keys = NULL; + int i; + + keys = sc_get_keys(sc_reader_id, NULL); + if (keys == NULL) + fatal("cannot read public key from smartcard"); + for (i = 0; keys[i]; i++) { + key_write(keys[i], stdout); + key_free(keys[i]); + fprintf(stdout, "\n"); + } + xfree(keys); + exit(0); +} +#endif /* SMARTCARD */ + +static void do_fingerprint(struct passwd *pw) { FILE *f; Key *public; char *comment = NULL, *cp, *ep, line[16*1024], *fp; - int i, skip = 0, num = 1, invalid = 1, rep, fptype; + int i, skip = 0, num = 1, invalid = 1; + enum fp_rep rep; + enum fp_type fptype; struct stat st; fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; @@ -377,7 +462,7 @@ public = key_load_public(identity_file, &comment); if (public != NULL) { fp = key_fingerprint(public, fptype, rep); - printf("%d %s %s\n", key_size(public), fp, comment); + printf("%u %s %s\n", key_size(public), fp, comment); key_free(public); xfree(comment); xfree(fp); @@ -411,7 +496,8 @@ if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { int quoted = 0; comment = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { + for (; *cp && (quoted || (*cp != ' ' && + *cp != '\t')); cp++) { if (*cp == '\\' && cp[1] == '"') cp++; /* Skip both */ else if (*cp == '"') @@ -434,7 +520,7 @@ } comment = *cp ? cp : comment; fp = key_fingerprint(public, fptype, rep); - printf("%d %s %s\n", key_size(public), fp, + printf("%u %s %s\n", key_size(public), fp, comment ? comment : "no comment"); xfree(fp); key_free(public); @@ -443,7 +529,7 @@ fclose(f); } if (invalid) { - printf("%s is not a valid key file.\n", identity_file); + printf("%s is not a public key file.\n", identity_file); exit(1); } exit(0); @@ -453,7 +539,7 @@ * Perform changing a passphrase. The argument is the passwd structure * for the current user. */ -void +static void do_change_passphrase(struct passwd *pw) { char *comment; @@ -473,8 +559,11 @@ if (identity_passphrase) old_passphrase = xstrdup(identity_passphrase); else - old_passphrase = read_passphrase("Enter old passphrase: ", 1); - private = key_load_private(identity_file, old_passphrase , &comment); + old_passphrase = + read_passphrase("Enter old passphrase: ", + RP_ALLOW_STDIN); + private = key_load_private(identity_file, old_passphrase, + &comment); memset(old_passphrase, 0, strlen(old_passphrase)); xfree(old_passphrase); if (private == NULL) { @@ -490,8 +579,10 @@ passphrase2 = NULL; } else { passphrase1 = - read_passphrase("Enter new passphrase (empty for no passphrase): ", 1); - passphrase2 = read_passphrase("Enter same passphrase again: ", 1); + read_passphrase("Enter new passphrase (empty for no " + "passphrase): ", RP_ALLOW_STDIN); + passphrase2 = read_passphrase("Enter same passphrase again: ", + RP_ALLOW_STDIN); /* Verify that they are the same. */ if (strcmp(passphrase1, passphrase2) != 0) { @@ -529,7 +620,7 @@ /* * Change the comment of a private key file. */ -void +static void do_change_comment(struct passwd *pw) { char new_comment[1024], *comment, *passphrase; @@ -552,7 +643,8 @@ else if (identity_new_passphrase) passphrase = xstrdup(identity_new_passphrase); else - passphrase = read_passphrase("Enter passphrase: ", 1); + passphrase = read_passphrase("Enter passphrase: ", + RP_ALLOW_STDIN); /* Try to load using the passphrase. */ private = key_load_private(identity_file, passphrase, &comment); if (private == NULL) { @@ -568,7 +660,7 @@ fprintf(stderr, "Comments are only supported for RSA1 keys.\n"); key_free(private); exit(1); - } + } printf("Key now has comment '%s'\n", comment); if (identity_comment) { @@ -622,11 +714,30 @@ exit(0); } -void +static void usage(void) { - printf("Usage: %s [-ceilpqyB] [-t type] [-b bits] [-f file] [-C comment] " - "[-N new-pass] [-P pass]\n", __progname); + fprintf(stderr, "Usage: %s [options]\n", __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -b bits Number of bits in the key to create.\n"); + fprintf(stderr, " -c Change comment in private and public key files.\n"); + fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); + fprintf(stderr, " -f filename Filename of the key file.\n"); + fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); + fprintf(stderr, " -l Show fingerprint of key file.\n"); + fprintf(stderr, " -p Change passphrase of private key file.\n"); + fprintf(stderr, " -q Quiet.\n"); + fprintf(stderr, " -y Read private key file and print public key.\n"); + fprintf(stderr, " -t type Specify type of key to create.\n"); + fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); + fprintf(stderr, " -C comment Provide new comment.\n"); + fprintf(stderr, " -N phrase Provide new passphrase.\n"); + fprintf(stderr, " -P phrase Provide old passphrase.\n"); +#ifdef SMARTCARD + fprintf(stderr, " -D reader Download public key from smartcard.\n"); + fprintf(stderr, " -U reader Upload private key to smartcard.\n"); +#endif /* SMARTCARD */ + exit(1); } @@ -636,16 +747,19 @@ int main(int ac, char **av) { - char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2; + char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; + char *reader_id = NULL; Key *private, *public; struct passwd *pw; - int opt, type, fd; struct stat st; + int opt, type, fd, download = 0; FILE *f; extern int optind; extern char *optarg; + __progname = get_progname(av[0]); + SSLeay_add_all_algorithms(); /* we need this for the home * directory. */ @@ -659,7 +773,7 @@ exit(1); } - while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:P:N:C:")) != -1) { + while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:U:D:P:N:C:")) != -1) { switch (opt) { case 'b': bits = atoi(optarg); @@ -668,73 +782,62 @@ exit(1); } break; - case 'l': print_fingerprint = 1; break; - case 'B': print_bubblebabble = 1; break; - case 'p': change_passphrase = 1; break; - case 'c': change_comment = 1; break; - case 'f': strlcpy(identity_file, optarg, sizeof(identity_file)); have_identity = 1; break; - case 'P': identity_passphrase = optarg; break; - case 'N': identity_new_passphrase = optarg; break; - case 'C': identity_comment = optarg; break; - case 'q': quiet = 1; break; - case 'R': /* unused */ exit(0); break; - case 'e': case 'x': /* export key */ convert_to_ssh2 = 1; break; - case 'i': case 'X': /* import key */ convert_from_ssh2 = 1; break; - case 'y': print_public = 1; break; - case 'd': key_type_name = "dsa"; break; - case 't': key_type_name = optarg; break; - + case 'D': + download = 1; + case 'U': + reader_id = optarg; + break; case '?': default: usage(); @@ -752,17 +855,34 @@ do_fingerprint(pw); if (change_passphrase) do_change_passphrase(pw); - if (change_comment) - do_change_comment(pw); if (convert_to_ssh2) do_convert_to_ssh2(pw); - if (convert_from_ssh2) - do_convert_from_ssh2(pw); + if (change_comment) + do_change_comment(pw); if (print_public) do_print_public(pw); + if (reader_id != NULL) { +#ifdef SMARTCARD + if (download) + do_download(pw, reader_id); + else + do_upload(pw, reader_id); +#else /* SMARTCARD */ + fatal("no support for smartcards."); +#endif /* SMARTCARD */ + } + init_rng(); + seed_rng(); arc4random_stir(); + if (convert_from_ssh2) + do_convert_from_ssh2(pw); + + if (key_type_name == NULL) { + printf("You must specify a key type (-t).\n"); + usage(); + } type = key_type_from_name(key_type_name); if (type == KEY_UNSPEC) { fprintf(stderr, "unknown key type %s\n", key_type_name); @@ -808,10 +928,15 @@ else { passphrase_again: passphrase1 = - read_passphrase("Enter passphrase (empty for no passphrase): ", 1); - passphrase2 = read_passphrase("Enter same passphrase again: ", 1); + read_passphrase("Enter passphrase (empty for no " + "passphrase): ", RP_ALLOW_STDIN); + passphrase2 = read_passphrase("Enter same passphrase again: ", + RP_ALLOW_STDIN); if (strcmp(passphrase1, passphrase2) != 0) { - /* The passphrases do not match. Clear them and retry. */ + /* + * The passphrases do not match. Clear them and + * retry. + */ memset(passphrase1, 0, strlen(passphrase1)); memset(passphrase2, 0, strlen(passphrase2)); xfree(passphrase1); Index: src/crypto/openssh/ssh-keyscan.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-keyscan.1,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh-keyscan.1 --- src/crypto/openssh/ssh-keyscan.1 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh-keyscan.1 30 Jun 2002 11:38:01 -0000 @@ -1,11 +1,10 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.5 2001/04/18 16:21:05 ian Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.14 2002/02/13 08:33:47 mpech Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" .\" Modification and redistribution in source and binary forms is .\" permitted provided that due credit is given to the author and the -.\" OpenBSD project (for instance by leaving this copyright notice -.\" intact). +.\" OpenBSD project by leaving this copyright notice intact. .\" .Dd January 1, 1996 .Dt SSH-KEYSCAN 1 @@ -15,9 +14,13 @@ .Nd gather ssh public keys .Sh SYNOPSIS .Nm ssh-keyscan -.Op Fl t Ar timeout -.Op Ar -- | host | addrlist namelist -.Op Fl f Ar files ... +.Op Fl v46 +.Op Fl p Ar port +.Op Fl T Ar timeout +.Op Fl t Ar type +.Op Fl f Ar file +.Op Ar host | addrlist namelist +.Op Ar ... .Sh DESCRIPTION .Nm is a utility for gathering the public ssh host keys of a number of @@ -32,46 +35,76 @@ uses non-blocking socket I/O to contact as many hosts as possible in parallel, so it is very efficient. The keys from a domain of 1,000 hosts can be collected in tens of seconds, even when some of those -hosts are down or do not run ssh. You do not need login access to the -machines you are scanning, nor does the scanning process involve -any encryption. -.Sh SECURITY -If you make an ssh_known_hosts file using -.Nm -without verifying the keys, you will be vulnerable to -.I man in the middle -attacks. -On the other hand, if your security model allows such a risk, -.Nm -can help you detect tampered keyfiles or man in the middle attacks which -have begun after you created your ssh_known_hosts file. -.Sh OPTIONS +hosts are down or do not run ssh. For scanning, one does not need +login access to the machines that are being scanned, nor does the +scanning process involve any encryption. +.Pp +The options are as follows: .Bl -tag -width Ds -.It Fl t -Set the timeout for connection attempts. If +.It Fl p Ar port +Port to connect to on the remote host. +.It Fl T Ar timeout +Set the timeout for connection attempts. If .Pa timeout seconds have elapsed since a connection was initiated to a host or since the last time anything was read from that host, then the connection is closed and the host in question considered unavailable. Default is 5 seconds. -.It Fl f -Read hosts or +.It Fl t Ar type +Specifies the type of the key to fetch from the scanned hosts. +The possible values are +.Dq rsa1 +for protocol version 1 and +.Dq rsa +or +.Dq dsa +for protocol version 2. +Multiple values may be specified by separating them with commas. +The default is +.Dq rsa1 . +.It Fl f Ar filename +Read hosts or .Pa addrlist namelist pairs from this file, one per line. If .Pa - is supplied instead of a filename, .Nm -will read hosts or +will read hosts or .Pa addrlist namelist pairs from the standard input. +.It Fl v +Verbose mode. +Causes +.Nm +to print debugging messages about its progress. +.It Fl 4 +Forces +.Nm +to use IPv4 addresses only. +.It Fl 6 +Forces +.Nm +to use IPv6 addresses only. .El +.Sh SECURITY +If a ssh_known_hosts file is constructed using +.Nm +without verifying the keys, users will be vulnerable to +.I man in the middle +attacks. +On the other hand, if the security model allows such a risk, +.Nm +can help in the detection of tampered keyfiles or man in the middle +attacks which have begun after the ssh_known_hosts file was created. .Sh EXAMPLES .Pp -Print the host key for machine +Print the +.Pa rsa1 +host key for machine .Pa hostname : .Bd -literal -ssh-keyscan hostname +$ ssh-keyscan hostname .Ed .Pp Find all hosts from the file @@ -79,26 +112,43 @@ which have new or different keys from those in the sorted file .Pa ssh_known_hosts : .Bd -literal -$ ssh-keyscan -f ssh_hosts | sort -u - ssh_known_hosts | \e\ - diff ssh_known_hosts - +$ ssh-keyscan -t rsa,dsa -f ssh_hosts | \e\ + sort -u - ssh_known_hosts | diff ssh_known_hosts - .Ed -.Pp .Sh FILES -.Pp .Pa Input format: +.Bd -literal 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 +.Ed .Pp -.Pa Output format: +.Pa Output format for rsa1 keys: +.Bd -literal host-or-namelist bits exponent modulus +.Ed +.Pp +.Pa Output format for rsa and dsa keys: +.Bd -literal +host-or-namelist keytype base64-encoded-key +.Ed +.Pp +Where +.Pa keytype +is either +.Dq ssh-rsa +or +.Dq ssh-dsa . .Pp -.Pa /etc/ssh_known_hosts +.Pa /etc/ssh/ssh_known_hosts .Sh BUGS It generates "Connection closed by remote host" messages on the consoles -of all the machines it scans. +of all the machines it scans if the server is older than version 2.9. This is because it opens a connection to the ssh port, reads the public key, and drops the connection as soon as it gets the key. .Sh SEE ALSO .Xr ssh 1 , .Xr sshd 8 -.Sh AUTHOR +.Sh AUTHORS David Mazieres +wrote the initial version, and +Wayne Davison +added support for protocol version 2. Index: src/crypto/openssh/ssh-keyscan.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-keyscan.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh-keyscan.c --- src/crypto/openssh/ssh-keyscan.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh-keyscan.c 30 Jun 2002 11:38:01 -0000 @@ -3,30 +3,47 @@ * * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the - * OpenBSD project (for instance by leaving this copyright notice - * intact). + * OpenBSD project by leaving this copyright notice intact. */ #include "includes.h" -RCSID("$OpenBSD: ssh-keyscan.c,v 1.22 2001/03/06 06:11:18 deraadt Exp $"); +RCSID("$OpenBSD: ssh-keyscan.c,v 1.36 2002/06/16 21:30:58 itojun Exp $"); -#include -#include +#include "openbsd-compat/fake-queue.h" #include +#include #include "xmalloc.h" #include "ssh.h" #include "ssh1.h" #include "key.h" +#include "kex.h" +#include "compat.h" +#include "myproposal.h" +#include "packet.h" +#include "dispatch.h" #include "buffer.h" #include "bufaux.h" #include "log.h" #include "atomicio.h" +#include "misc.h" -static int argno = 1; /* Number of argument currently being parsed */ +/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. + Default value is AF_UNSPEC means both IPv4 and IPv6. */ +#ifdef IPV4_DEFAULT +int IPv4or6 = AF_INET; +#else +int IPv4or6 = AF_UNSPEC; +#endif + +int ssh_port = SSH_DEFAULT_PORT; + +#define KT_RSA1 1 +#define KT_DSA 2 +#define KT_RSA 4 -int family = AF_UNSPEC; /* IPv4, IPv6 or both */ +int get_keytypes = KT_RSA1; /* Get only RSA1 keys by default */ #define MAXMAXFD 256 @@ -36,10 +53,17 @@ int maxfd; #define MAXCON (maxfd - 10) +#ifdef HAVE___PROGNAME extern char *__progname; +#else +char *__progname; +#endif fd_set *read_wait; size_t read_wait_size; int ncon; +int nonfatal_fatal = 0; +jmp_buf kexjmp; +Key *kexjmp_key; /* * Keep a connection structure for each file descriptor. The state @@ -55,11 +79,13 @@ int c_plen; /* Packet length field for ssh packet */ int c_len; /* Total bytes which must be read. */ int c_off; /* Length of data read so far. */ + int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ char *c_namebase; /* Address to free for c_name and c_namelist */ char *c_name; /* Hostname of connection for errors */ char *c_namelist; /* Pointer to other possible addresses */ char *c_output_name; /* Hostname of connection for output */ char *c_data; /* Data read from this fd */ + Kex *c_kex; /* The key-exchange struct for ssh2 */ struct timeval c_tv; /* Time at which connection gets aborted */ TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */ } con; @@ -83,7 +109,7 @@ void (*errfun) (const char *,...); } Linebuf; -Linebuf * +static Linebuf * Linebuf_alloc(const char *filename, void (*errfun) (const char *,...)) { Linebuf *lb; @@ -117,7 +143,7 @@ return (lb); } -void +static void Linebuf_free(Linebuf * lb) { fclose(lb->stream); @@ -125,7 +151,8 @@ xfree(lb); } -void +#if 0 +static void Linebuf_restart(Linebuf * lb) { clearerr(lb->stream); @@ -133,13 +160,14 @@ lb->lineno = 0; } -int +static int Linebuf_lineno(Linebuf * lb) { return (lb->lineno); } +#endif -char * +static char * Linebuf_getline(Linebuf * lb) { int n = 0; @@ -176,9 +204,10 @@ } } -int +static int fdlim_get(int hard) { +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) struct rlimit rlfd; if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0) @@ -187,19 +216,30 @@ return 10000; else return hard ? rlfd.rlim_max : rlfd.rlim_cur; +#elif defined (HAVE_SYSCONF) + return sysconf (_SC_OPEN_MAX); +#else + return 10000; +#endif } -int +static int fdlim_set(int lim) { +#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) struct rlimit rlfd; +#endif if (lim <= 0) return (-1); +#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0) return (-1); rlfd.rlim_cur = lim; if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0) return (-1); +#elif defined (HAVE_SETDTABLESIZE) + setdtablesize(lim); +#endif return (0); } @@ -208,7 +248,7 @@ * separators. This is the same as the 4.4BSD strsep, but different from the * one in the GNU libc. */ -char * +static char * xstrsep(char **str, const char *delim) { char *s, *e; @@ -230,7 +270,7 @@ * Get the next non-null token (like GNU strsep). Strsep() will return a * null token for two adjacent separators, so we may have to loop. */ -char * +static char * strnnsep(char **stringp, char *delim) { char *tok; @@ -241,8 +281,8 @@ return (tok); } -void -keyprint(char *host, char *output_name, char *kd, int len) +static Key * +keygrab_ssh1(con *c) { static Key *rsa; static Buffer msg; @@ -251,12 +291,12 @@ buffer_init(&msg); rsa = key_new(KEY_RSA1); } - buffer_append(&msg, kd, len); - buffer_consume(&msg, 8 - (len & 7)); /* padding */ + buffer_append(&msg, c->c_data, c->c_plen); + buffer_consume(&msg, 8 - (c->c_plen & 7)); /* padding */ if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) { - error("%s: invalid packet type", host); + error("%s: invalid packet type", c->c_name); buffer_clear(&msg); - return; + return NULL; } buffer_consume(&msg, 8); /* cookie */ @@ -269,23 +309,82 @@ (void) buffer_get_int(&msg); buffer_get_bignum(&msg, rsa->rsa->e); buffer_get_bignum(&msg, rsa->rsa->n); + buffer_clear(&msg); - fprintf(stdout, "%s ", output_name ? output_name : host); - key_write(rsa, stdout); + return (rsa); +} + +static int +hostjump(Key *hostkey) +{ + kexjmp_key = hostkey; + longjmp(kexjmp, 1); +} + +static int +ssh2_capable(int remote_major, int remote_minor) +{ + switch (remote_major) { + case 1: + if (remote_minor == 99) + return 1; + break; + case 2: + return 1; + default: + break; + } + return 0; +} + +static Key * +keygrab_ssh2(con *c) +{ + int j; + + packet_set_connection(c->c_fd, c->c_fd); + enable_compat20(); + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? + "ssh-dss": "ssh-rsa"; + c->c_kex = kex_setup(myproposal); + c->c_kex->verify_host_key = hostjump; + + if (!(j = setjmp(kexjmp))) { + nonfatal_fatal = 1; + dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, c->c_kex); + fprintf(stderr, "Impossible! dispatch_run() returned!\n"); + exit(1); + } + nonfatal_fatal = 0; + xfree(c->c_kex); + c->c_kex = NULL; + packet_close(); + + return j < 0? NULL : kexjmp_key; +} + +static void +keyprint(con *c, Key *key) +{ + if (!key) + return; + + fprintf(stdout, "%s ", c->c_output_name ? c->c_output_name : c->c_name); + key_write(key, stdout); fputs("\n", stdout); } -int +static int tcpconnect(char *host) { struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, s = -1; - snprintf(strport, sizeof strport, "%d", SSH_DEFAULT_PORT); + snprintf(strport, sizeof strport, "%d", ssh_port); memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; + hints.ai_family = IPv4or6; hints.ai_socktype = SOCK_STREAM; if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) fatal("getaddrinfo %s: %s", host, gai_strerror(gaierr)); @@ -309,8 +408,8 @@ return s; } -int -conalloc(char *iname, char *oname) +static int +conalloc(char *iname, char *oname, int keytype) { int s; char *namebase, *name, *namelist; @@ -339,6 +438,7 @@ fdcon[s].c_data = (char *) &fdcon[s].c_plen; fdcon[s].c_len = 4; fdcon[s].c_off = 0; + fdcon[s].c_keytype = keytype; gettimeofday(&fdcon[s].c_tv, NULL); fdcon[s].c_tv.tv_sec += timeout; TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); @@ -347,7 +447,7 @@ return (s); } -void +static void confree(int s) { if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) @@ -358,12 +458,13 @@ if (fdcon[s].c_status == CS_KEYS) xfree(fdcon[s].c_data); fdcon[s].c_status = CS_UNUSED; + fdcon[s].c_keytype = 0; TAILQ_REMOVE(&tq, &fdcon[s], c_link); FD_CLR(s, read_wait); ncon--; } -void +static void contouch(int s) { TAILQ_REMOVE(&tq, &fdcon[s], c_link); @@ -372,58 +473,85 @@ TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); } -int +static int conrecycle(int s) { int ret; con *c = &fdcon[s]; - char *iname, *oname; - iname = xstrdup(c->c_namelist); - oname = xstrdup(c->c_output_name); + ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); confree(s); - ret = conalloc(iname, oname); - xfree(iname); - xfree(oname); return (ret); } -void +static void congreet(int s) { - char buf[80], *cp; + char buf[256], *cp; + char remote_version[sizeof buf]; size_t bufsiz; - int n = 0; + int remote_major, remote_minor, n = 0; con *c = &fdcon[s]; bufsiz = sizeof(buf); cp = buf; - while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n' && *cp != '\r') + while (bufsiz-- && (n = read(s, cp, 1)) == 1 && *cp != '\n') { + if (*cp == '\r') + *cp = '\n'; cp++; + } if (n < 0) { if (errno != ECONNREFUSED) error("read (%s): %s", c->c_name, strerror(errno)); conrecycle(s); return; } + if (n == 0) { + error("%s: Connection closed by remote host", c->c_name); + conrecycle(s); + return; + } if (*cp != '\n' && *cp != '\r') { error("%s: bad greeting", c->c_name); confree(s); return; } *cp = '\0'; - fprintf(stderr, "# %s %s\n", c->c_name, buf); - n = snprintf(buf, sizeof buf, "SSH-1.5-OpenSSH-keyscan\r\n"); + if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", + &remote_major, &remote_minor, remote_version) == 3) + compat_datafellows(remote_version); + else + datafellows = 0; + if (c->c_keytype != KT_RSA1) { + if (!ssh2_capable(remote_major, remote_minor)) { + debug("%s doesn't support ssh2", c->c_name); + confree(s); + return; + } + } else if (remote_major != 1) { + debug("%s doesn't support ssh1", c->c_name); + confree(s); + return; + } + fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); + n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", + c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, + c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); if (atomicio(write, s, buf, n) != n) { error("write (%s): %s", c->c_name, strerror(errno)); confree(s); return; } + if (c->c_keytype != KT_RSA1) { + keyprint(c, keygrab_ssh2(c)); + confree(s); + return; + } c->c_status = CS_SIZE; contouch(s); } -void +static void conread(int s) { int n; @@ -451,7 +579,7 @@ c->c_status = CS_KEYS; break; case CS_KEYS: - keyprint(c->c_name, c->c_output_name, c->c_data, c->c_plen); + keyprint(c, keygrab_ssh1(c)); confree(s); return; break; @@ -463,7 +591,7 @@ contouch(s); } -void +static void conloop(void) { fd_set *r, *e; @@ -472,7 +600,7 @@ con *c; gettimeofday(&now, NULL); - c = tq.tqh_first; + c = TAILQ_FIRST(&tq); if (c && (c->c_tv.tv_sec > now.tv_sec || (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) { @@ -505,91 +633,146 @@ xfree(r); xfree(e); - c = tq.tqh_first; + c = TAILQ_FIRST(&tq); while (c && (c->c_tv.tv_sec < now.tv_sec || (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { int s = c->c_fd; - c = c->c_link.tqe_next; + c = TAILQ_NEXT(c, c_link); conrecycle(s); } } -char * -nexthost(int argc, char **argv) +static void +do_host(char *host) { - static Linebuf *lb; + char *name = strnnsep(&host, " \t\n"); + int j; - for (;;) { - if (!lb) { - if (argno >= argc) - return (NULL); - if (argv[argno][0] != '-') - return (argv[argno++]); - if (!strcmp(argv[argno], "--")) { - if (++argno >= argc) - return (NULL); - return (argv[argno++]); - } else if (!strncmp(argv[argno], "-f", 2)) { - char *fname; - - if (argv[argno][2]) - fname = &argv[argno++][2]; - else if (++argno >= argc) { - error("missing filename for `-f'"); - return (NULL); - } else - fname = argv[argno++]; - if (!strcmp(fname, "-")) - fname = NULL; - lb = Linebuf_alloc(fname, error); - } else - error("ignoring invalid/misplaced option `%s'", - argv[argno++]); - } else { - char *line; - - line = Linebuf_getline(lb); - if (line) - return (line); - Linebuf_free(lb); - lb = NULL; + if (name == NULL) + return; + for (j = KT_RSA1; j <= KT_RSA; j *= 2) { + if (get_keytypes & j) { + while (ncon >= MAXCON) + conloop(); + conalloc(name, *host ? host : name, j); } } } void +fatal(const char *fmt,...) +{ + va_list args; + va_start(args, fmt); + do_log(SYSLOG_LEVEL_FATAL, fmt, args); + va_end(args); + if (nonfatal_fatal) + longjmp(kexjmp, -1); + else + fatal_cleanup(); +} + +static void usage(void) { - fatal("usage: %s [-t timeout] { [--] host | -f file } ...", __progname); - return; + fprintf(stderr, "Usage: %s [options] host ...\n", + __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -f file Read hosts or addresses from file.\n"); + fprintf(stderr, " -p port Connect to the specified port.\n"); + fprintf(stderr, " -t keytype Specify the host key type.\n"); + fprintf(stderr, " -T timeout Set connection timeout.\n"); + fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); + fprintf(stderr, " -4 Use IPv4 only.\n"); + fprintf(stderr, " -6 Use IPv6 only.\n"); + exit(1); } int main(int argc, char **argv) { - char *host = NULL; - + int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO; + int opt, fopt_count = 0; + char *tname; + + extern int optind; + extern char *optarg; + + __progname = get_progname(argv[0]); + init_rng(); + seed_rng(); TAILQ_INIT(&tq); - if (argc <= argno) + if (argc <= 1) usage(); - if (argv[1][0] == '-' && argv[1][1] == 't') { - argno++; - if (argv[1][2]) - timeout = atoi(&argv[1][2]); - else { - if (argno >= argc) + while ((opt = getopt(argc, argv, "v46p:T:t:f:")) != -1) { + switch (opt) { + case 'p': + ssh_port = a2port(optarg); + if (ssh_port == 0) { + fprintf(stderr, "Bad port '%s'\n", optarg); + exit(1); + } + break; + case 'T': + timeout = atoi(optarg); + if (timeout <= 0) usage(); - timeout = atoi(argv[argno++]); - } - if (timeout <= 0) + break; + case 'v': + if (!debug_flag) { + debug_flag = 1; + log_level = SYSLOG_LEVEL_DEBUG1; + } + else if (log_level < SYSLOG_LEVEL_DEBUG3) + log_level++; + else + fatal("Too high debugging level."); + break; + case 'f': + if (strcmp(optarg, "-") == 0) + optarg = NULL; + argv[fopt_count++] = optarg; + break; + case 't': + get_keytypes = 0; + tname = strtok(optarg, ","); + while (tname) { + int type = key_type_from_name(tname); + switch (type) { + case KEY_RSA1: + get_keytypes |= KT_RSA1; + break; + case KEY_DSA: + get_keytypes |= KT_DSA; + break; + case KEY_RSA: + get_keytypes |= KT_RSA; + break; + case KEY_UNSPEC: + fatal("unknown key type %s", tname); + } + tname = strtok(NULL, ","); + } + break; + case '4': + IPv4or6 = AF_INET; + break; + case '6': + IPv4or6 = AF_INET6; + break; + case '?': + default: usage(); + } } - if (argc <= argno) + if (optind == argc && !fopt_count) usage(); + log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); + maxfd = fdlim_get(1); if (maxfd < 0) fatal("%s: fdlim_get: bad value", __progname); @@ -606,18 +789,24 @@ read_wait = xmalloc(read_wait_size); memset(read_wait, 0, read_wait_size); - do { - while (ncon < MAXCON) { - char *name; - - host = nexthost(argc, argv); - if (host == NULL) - break; - name = strnnsep(&host, " \t\n"); - conalloc(name, *host ? host : name); + if (fopt_count) { + Linebuf *lb; + char *line; + int j; + + for (j = 0; j < fopt_count; j++) { + lb = Linebuf_alloc(argv[j], error); + if (!lb) + continue; + while ((line = Linebuf_getline(lb)) != NULL) + do_host(line); + Linebuf_free(lb); } - conloop(); - } while (host); + } + + while (optind < argc) + do_host(argv[optind++]); + while (ncon > 0) conloop(); Index: src/crypto/openssh/ssh-keysign.8 =================================================================== RCS file: src/crypto/openssh/ssh-keysign.8 diff -N src/crypto/openssh/ssh-keysign.8 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ssh-keysign.8 30 Jun 2002 11:38:01 -0000 @@ -0,0 +1,67 @@ +.\" $OpenBSD: ssh-keysign.8,v 1.2 2002/06/10 16:56:30 stevesk Exp $ +.\" +.\" Copyright (c) 2002 Markus Friedl. 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd May 24, 2002 +.Dt SSH-KEYSIGN 8 +.Os +.Sh NAME +.Nm ssh-keysign +.Nd ssh helper program for hostbased authentication +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +.Nm +is used by +.Xr ssh 1 +to access the local host keys and generate the digital signature +required during hostbased authentication with SSH protocol version 2. +.Nm +is not intended to be invoked by the user, but from +.Xr ssh 1 . +See +.Xr ssh 1 +and +.Xr sshd 8 +for more information about hostbased authentication. +.Sh FILES +.Bl -tag -width Ds +.It Pa /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key +These files contain the private parts of the host keys used to +generate the digital signature. They +should be owned by root, readable only by root, and not +accessible to others. +Since they are readable only by root, +.Nm +must be set-uid root if hostbased authentication is used. +.El +.Sh SEE ALSO +.Xr ssh 1 , +.Xr ssh-keygen 1 , +.Xr sshd 8 +.Sh AUTHORS +Markus Friedl +.Sh HISTORY +.Nm +first appeared in +.Ox 3.2 . Index: src/crypto/openssh/ssh-keysign.c =================================================================== RCS file: src/crypto/openssh/ssh-keysign.c diff -N src/crypto/openssh/ssh-keysign.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ssh-keysign.c 30 Jun 2002 11:38:01 -0000 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2002 Markus Friedl. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "includes.h" +RCSID("$OpenBSD: ssh-keysign.c,v 1.4 2002/06/19 00:27:55 deraadt Exp $"); + +#include + +#include "log.h" +#include "key.h" +#include "ssh2.h" +#include "misc.h" +#include "xmalloc.h" +#include "buffer.h" +#include "bufaux.h" +#include "authfile.h" +#include "msg.h" +#include "canohost.h" +#include "pathnames.h" + +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif + +static int +valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, + u_int datalen) +{ + Buffer b; + Key *key; + u_char *pkblob; + u_int blen, len; + char *pkalg, *p; + int pktype, fail; + + fail = 0; + + buffer_init(&b); + buffer_append(&b, data, datalen); + + /* session id, currently limited to SHA1 (20 bytes) */ + p = buffer_get_string(&b, &len); + if (len != 20) + fail++; + xfree(p); + + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + + /* server user */ + buffer_skip_string(&b); + + /* service */ + p = buffer_get_string(&b, NULL); + if (strcmp("ssh-connection", p) != 0) + fail++; + xfree(p); + + /* method */ + p = buffer_get_string(&b, NULL); + if (strcmp("hostbased", p) != 0) + fail++; + xfree(p); + + /* pubkey */ + pkalg = buffer_get_string(&b, NULL); + pkblob = buffer_get_string(&b, &blen); + + pktype = key_type_from_name(pkalg); + if (pktype == KEY_UNSPEC) + fail++; + else if ((key = key_from_blob(pkblob, blen)) == NULL) + fail++; + else if (key->type != pktype) + fail++; + xfree(pkalg); + xfree(pkblob); + + /* client host name, handle trailing dot */ + p = buffer_get_string(&b, &len); + debug2("valid_request: check expect chost %s got %s", host, p); + if (strlen(host) != len - 1) + fail++; + else if (p[len - 1] != '.') + fail++; + else if (strncasecmp(host, p, len - 1) != 0) + fail++; + xfree(p); + + /* local user */ + p = buffer_get_string(&b, NULL); + + if (strcmp(pw->pw_name, p) != 0) + fail++; + xfree(p); + + /* end of message */ + if (buffer_len(&b) != 0) + fail++; + + debug3("valid_request: fail %d", fail); + + if (fail && key != NULL) + key_free(key); + else + *ret = key; + + return (fail ? -1 : 0); +} + +int +main(int argc, char **argv) +{ + Buffer b; + Key *keys[2], *key; + struct passwd *pw; + int key_fd[2], i, found, version = 2, fd; + u_char *signature, *data; + char *host; + u_int slen, dlen; + + key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); + key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); + + seteuid(getuid()); + setuid(getuid()); + + init_rng(); + seed_rng(); + arc4random_stir(); + +#ifdef DEBUG_SSH_KEYSIGN + log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); +#endif + + if (key_fd[0] == -1 && key_fd[1] == -1) + fatal("could not open any host key"); + + if ((pw = getpwuid(getuid())) == NULL) + fatal("getpwuid failed"); + pw = pwcopy(pw); + + SSLeay_add_all_algorithms(); + + found = 0; + for (i = 0; i < 2; i++) { + keys[i] = NULL; + if (key_fd[i] == -1) + continue; + keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, + NULL, NULL); + close(key_fd[i]); + if (keys[i] != NULL) + found = 1; + } + if (!found) + fatal("no hostkey found"); + + buffer_init(&b); + if (msg_recv(STDIN_FILENO, &b) < 0) + fatal("msg_recv failed"); + if (buffer_get_char(&b) != version) + fatal("bad version"); + fd = buffer_get_int(&b); + if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO)) + fatal("bad fd"); + if ((host = get_local_name(fd)) == NULL) + fatal("cannot get sockname for fd"); + + data = buffer_get_string(&b, &dlen); + if (valid_request(pw, host, &key, data, dlen) < 0) + fatal("not a valid request"); + xfree(data); + xfree(host); + + found = 0; + for (i = 0; i < 2; i++) { + if (keys[i] != NULL && + key_equal(key, keys[i])) { + found = 1; + break; + } + } + if (!found) + fatal("no matching hostkey found"); + + if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) + fatal("key_sign failed"); + + /* send reply */ + buffer_clear(&b); + buffer_put_string(&b, signature, slen); + msg_send(STDOUT_FILENO, version, &b); + + return (0); +} Index: src/crypto/openssh/ssh-rand-helper.8 =================================================================== RCS file: src/crypto/openssh/ssh-rand-helper.8 diff -N src/crypto/openssh/ssh-rand-helper.8 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ssh-rand-helper.8 30 Jun 2002 11:38:01 -0000 @@ -0,0 +1,94 @@ +.\" $Id$ +.\" +.\" Copyright (c) 2002 Damien Miller. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd April 14, 2002 +.Dt SSH-RAND-HELPER 8 +.Os +.Sh NAME +.Nm ssh-rand-helper +.Nd Random number gatherer for OpenSSH +.Sh SYNOPSIS +.Nm ssh-rand-hlper +.Op Fl vxXh +.Op Fl b Ar bytes +.Sh DESCRIPTION +.Nm +is a small helper program used by +.Xr ssh 1 , +.Xr ssh-add 1 , +.Xr ssh-agent 1 , +.Xr ssh-keygen 1 , +.Xr ssh-keyscan 1 +and +.Xr sshd 8 +to gather random numbers of cryptographic quality if the +.Xr openssl 4 +library has not been configured to provide them itself. +.Pp +Normally +.Nm +will generate a strong random seed and provide it to the calling +program via standard output. If standard output is a tty, +.Nm +will instead print the seed in hexidecimal format unless told otherwise. +.Pp +.Nm +will by default gather random numbers from the system commands listed +in +.Pa /etc/ssh/ssh_prng_cmds . +The output of each of the commands listed will be hashed and used to +generate a random seed for the calling program. +.Nm +will also store seed files in +.Pa ~/.ssh/prng_seed +between executions. +.Pp +Alternately, +.Nm +may be configured at build time to collect random numbers from a +EGD/PRNGd server via a unix domain or localhost tcp socket. +.Pp +This program is not intended to be run by the end-user, so the few +commandline options are for debugging purposes only. +.Bl -tag -width Ds +.It Fl b Ar bytes +Specify the number of random bytes to include in the output. +.It Fl x +Output a hexidecimal instead of a binary seed. +.It Fl X +Force output of a binary seed, even if standard output is a tty +.It Fl v +Turn on debugging message. Multiple +.Fl v +options will increase the debugging level. +.Fl h +Display a summary of options. +.El +.Sh AUTHORS +Damien Miller +.Sh SEE ALSO +.Xr ssh 1 , +.Xr ssh-add 1 , +.Xr ssh-keygen 1 , +.Xr sshd 8 Index: src/crypto/openssh/ssh-rand-helper.c =================================================================== RCS file: src/crypto/openssh/ssh-rand-helper.c diff -N src/crypto/openssh/ssh-rand-helper.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ssh-rand-helper.c 30 Jun 2002 11:38:01 -0000 @@ -0,0 +1,865 @@ +/* + * Copyright (c) 2001-2002 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include +#include +#include + +/* SunOS 4.4.4 needs this */ +#ifdef HAVE_FLOATINGPOINT_H +# include +#endif /* HAVE_FLOATINGPOINT_H */ + +#include "misc.h" +#include "xmalloc.h" +#include "atomicio.h" +#include "pathnames.h" +#include "log.h" + +RCSID("$Id$"); + +/* Number of bytes we write out */ +#define OUTPUT_SEED_SIZE 48 + +/* Length of on-disk seedfiles */ +#define SEED_FILE_SIZE 1024 + +/* Maximum number of command-line arguments to read from file */ +#define NUM_ARGS 10 + +/* Minimum number of usable commands to be considered sufficient */ +#define MIN_ENTROPY_SOURCES 16 + +/* Path to on-disk seed file (relative to user's home directory */ +#ifndef SSH_PRNG_SEED_FILE +# define SSH_PRNG_SEED_FILE _PATH_SSH_USER_DIR"/prng_seed" +#endif + +/* Path to PRNG commands list */ +#ifndef SSH_PRNG_COMMAND_FILE +# define SSH_PRNG_COMMAND_FILE SSHDIR "/ssh_prng_cmds" +#endif + + +#ifdef HAVE___PROGNAME +extern char *__progname; +#else +char *__progname; +#endif + +#ifndef offsetof +# define offsetof(type, member) ((size_t) &((type *)0)->member) +#endif + +#define WHITESPACE " \t\n" + +#ifndef RUSAGE_SELF +# define RUSAGE_SELF 0 +#endif +#ifndef RUSAGE_CHILDREN +# define RUSAGE_CHILDREN 0 +#endif + +#if !defined(PRNGD_SOCKET) && !defined(PRNGD_PORT) +# define USE_SEED_FILES +#endif + +typedef struct { + /* Proportion of data that is entropy */ + double rate; + /* Counter goes positive if this command times out */ + unsigned int badness; + /* Increases by factor of two each timeout */ + unsigned int sticky_badness; + /* Path to executable */ + char *path; + /* argv to pass to executable */ + char *args[NUM_ARGS]; /* XXX: arbitrary limit */ + /* full command string (debug) */ + char *cmdstring; +} entropy_cmd_t; + +/* slow command timeouts (all in milliseconds) */ +/* static int entropy_timeout_default = ENTROPY_TIMEOUT_MSEC; */ +static int entropy_timeout_current = ENTROPY_TIMEOUT_MSEC; + +/* this is initialised from a file, by prng_read_commands() */ +static entropy_cmd_t *entropy_cmds = NULL; + +/* Prototypes */ +double stir_from_system(void); +double stir_from_programs(void); +double stir_gettimeofday(double entropy_estimate); +double stir_clock(double entropy_estimate); +double stir_rusage(int who, double entropy_estimate); +double hash_command_output(entropy_cmd_t *src, char *hash); +int get_random_bytes_prngd(unsigned char *buf, int len, + unsigned short tcp_port, char *socket_path); + +/* + * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon + * listening either on 'tcp_port', or via Unix domain socket at * + * 'socket_path'. + * Either a non-zero tcp_port or a non-null socket_path must be + * supplied. + * Returns 0 on success, -1 on error + */ +int +get_random_bytes_prngd(unsigned char *buf, int len, + unsigned short tcp_port, char *socket_path) +{ + int fd, addr_len, rval, errors; + char msg[2]; + struct sockaddr_storage addr; + struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr; + struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr; + mysig_t old_sigpipe; + + /* Sanity checks */ + if (socket_path == NULL && tcp_port == 0) + fatal("You must specify a port or a socket"); + if (socket_path != NULL && + strlen(socket_path) >= sizeof(addr_un->sun_path)) + fatal("Random pool path is too long"); + if (len > 255) + fatal("Too many bytes to read from PRNGD"); + + memset(&addr, '\0', sizeof(addr)); + + if (tcp_port != 0) { + addr_in->sin_family = AF_INET; + addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_in->sin_port = htons(tcp_port); + addr_len = sizeof(*addr_in); + } else { + addr_un->sun_family = AF_UNIX; + strlcpy(addr_un->sun_path, socket_path, + sizeof(addr_un->sun_path)); + addr_len = offsetof(struct sockaddr_un, sun_path) + + strlen(socket_path) + 1; + } + + old_sigpipe = mysignal(SIGPIPE, SIG_IGN); + + errors = 0; + rval = -1; +reopen: + fd = socket(addr.ss_family, SOCK_STREAM, 0); + if (fd == -1) { + error("Couldn't create socket: %s", strerror(errno)); + goto done; + } + + if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) { + if (tcp_port != 0) { + error("Couldn't connect to PRNGD port %d: %s", + tcp_port, strerror(errno)); + } else { + error("Couldn't connect to PRNGD socket \"%s\": %s", + addr_un->sun_path, strerror(errno)); + } + goto done; + } + + /* Send blocking read request to PRNGD */ + msg[0] = 0x02; + msg[1] = len; + + if (atomicio(write, fd, msg, sizeof(msg)) != sizeof(msg)) { + if (errno == EPIPE && errors < 10) { + close(fd); + errors++; + goto reopen; + } + error("Couldn't write to PRNGD socket: %s", + strerror(errno)); + goto done; + } + + if (atomicio(read, fd, buf, len) != len) { + if (errno == EPIPE && errors < 10) { + close(fd); + errors++; + goto reopen; + } + error("Couldn't read from PRNGD socket: %s", + strerror(errno)); + goto done; + } + + rval = 0; +done: + mysignal(SIGPIPE, old_sigpipe); + if (fd != -1) + close(fd); + return rval; +} + +double +stir_gettimeofday(double entropy_estimate) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL) == -1) + fatal("Couldn't gettimeofday: %s", strerror(errno)); + + RAND_add(&tv, sizeof(tv), entropy_estimate); + + return entropy_estimate; +} + +double +stir_clock(double entropy_estimate) +{ +#ifdef HAVE_CLOCK + clock_t c; + + c = clock(); + RAND_add(&c, sizeof(c), entropy_estimate); + + return entropy_estimate; +#else /* _HAVE_CLOCK */ + return 0; +#endif /* _HAVE_CLOCK */ +} + +double +stir_rusage(int who, double entropy_estimate) +{ +#ifdef HAVE_GETRUSAGE + struct rusage ru; + + if (getrusage(who, &ru) == -1) + return 0; + + RAND_add(&ru, sizeof(ru), entropy_estimate); + + return entropy_estimate; +#else /* _HAVE_GETRUSAGE */ + return 0; +#endif /* _HAVE_GETRUSAGE */ +} + +static int +timeval_diff(struct timeval *t1, struct timeval *t2) +{ + int secdiff, usecdiff; + + secdiff = t2->tv_sec - t1->tv_sec; + usecdiff = (secdiff*1000000) + (t2->tv_usec - t1->tv_usec); + return (int)(usecdiff / 1000); +} + +double +hash_command_output(entropy_cmd_t *src, char *hash) +{ + char buf[8192]; + fd_set rdset; + int bytes_read, cmd_eof, error_abort, msec_elapsed, p[2]; + int status, total_bytes_read; + static int devnull = -1; + pid_t pid; + SHA_CTX sha; + struct timeval tv_start, tv_current; + + debug3("Reading output from \'%s\'", src->cmdstring); + + if (devnull == -1) { + devnull = open("/dev/null", O_RDWR); + if (devnull == -1) + fatal("Couldn't open /dev/null: %s", + strerror(errno)); + } + + if (pipe(p) == -1) + fatal("Couldn't open pipe: %s", strerror(errno)); + + (void)gettimeofday(&tv_start, NULL); /* record start time */ + + switch (pid = fork()) { + case -1: /* Error */ + close(p[0]); + close(p[1]); + fatal("Couldn't fork: %s", strerror(errno)); + /* NOTREACHED */ + case 0: /* Child */ + dup2(devnull, STDIN_FILENO); + dup2(p[1], STDOUT_FILENO); + dup2(p[1], STDERR_FILENO); + close(p[0]); + close(p[1]); + close(devnull); + + execv(src->path, (char**)(src->args)); + + debug("(child) Couldn't exec '%s': %s", + src->cmdstring, strerror(errno)); + _exit(-1); + default: /* Parent */ + break; + } + + RAND_add(&pid, sizeof(&pid), 0.0); + + close(p[1]); + + /* Hash output from child */ + SHA1_Init(&sha); + + cmd_eof = error_abort = msec_elapsed = total_bytes_read = 0; + while (!error_abort && !cmd_eof) { + int ret; + struct timeval tv; + int msec_remaining; + + (void) gettimeofday(&tv_current, 0); + msec_elapsed = timeval_diff(&tv_start, &tv_current); + if (msec_elapsed >= entropy_timeout_current) { + error_abort=1; + continue; + } + msec_remaining = entropy_timeout_current - msec_elapsed; + + FD_ZERO(&rdset); + FD_SET(p[0], &rdset); + tv.tv_sec = msec_remaining / 1000; + tv.tv_usec = (msec_remaining % 1000) * 1000; + + ret = select(p[0] + 1, &rdset, NULL, NULL, &tv); + + RAND_add(&tv, sizeof(tv), 0.0); + + switch (ret) { + case 0: + /* timer expired */ + error_abort = 1; + break; + case 1: + /* command input */ + do { + bytes_read = read(p[0], buf, sizeof(buf)); + } while (bytes_read == -1 && errno == EINTR); + RAND_add(&bytes_read, sizeof(&bytes_read), 0.0); + if (bytes_read == -1) { + error_abort = 1; + break; + } else if (bytes_read) { + SHA1_Update(&sha, buf, bytes_read); + total_bytes_read += bytes_read; + } else { + cmd_eof = 1; + } + break; + case -1: + default: + /* error */ + debug("Command '%s': select() failed: %s", + src->cmdstring, strerror(errno)); + error_abort = 1; + break; + } + } + + SHA1_Final(hash, &sha); + + close(p[0]); + + debug3("Time elapsed: %d msec", msec_elapsed); + + if (waitpid(pid, &status, 0) == -1) { + error("Couldn't wait for child '%s' completion: %s", + src->cmdstring, strerror(errno)); + return 0.0; + } + + RAND_add(&status, sizeof(&status), 0.0); + + if (error_abort) { + /* + * Closing p[0] on timeout causes the entropy command to + * SIGPIPE. Take whatever output we got, and mark this + * command as slow + */ + debug2("Command '%s' timed out", src->cmdstring); + src->sticky_badness *= 2; + src->badness = src->sticky_badness; + return total_bytes_read; + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) { + return total_bytes_read; + } else { + debug2("Command '%s' exit status was %d", + src->cmdstring, WEXITSTATUS(status)); + src->badness = src->sticky_badness = 128; + return 0.0; + } + } else if (WIFSIGNALED(status)) { + debug2("Command '%s' returned on uncaught signal %d !", + src->cmdstring, status); + src->badness = src->sticky_badness = 128; + return 0.0; + } else + return 0.0; +} + +double +stir_from_system(void) +{ + double total_entropy_estimate; + long int i; + + total_entropy_estimate = 0; + + i = getpid(); + RAND_add(&i, sizeof(i), 0.5); + total_entropy_estimate += 0.1; + + i = getppid(); + RAND_add(&i, sizeof(i), 0.5); + total_entropy_estimate += 0.1; + + i = getuid(); + RAND_add(&i, sizeof(i), 0.0); + i = getgid(); + RAND_add(&i, sizeof(i), 0.0); + + total_entropy_estimate += stir_gettimeofday(1.0); + total_entropy_estimate += stir_clock(0.5); + total_entropy_estimate += stir_rusage(RUSAGE_SELF, 2.0); + + return total_entropy_estimate; +} + +double +stir_from_programs(void) +{ + int c; + double entropy, total_entropy; + char hash[SHA_DIGEST_LENGTH]; + + total_entropy = 0; + for(c = 0; entropy_cmds[c].path != NULL; c++) { + if (!entropy_cmds[c].badness) { + /* Hash output from command */ + entropy = hash_command_output(&entropy_cmds[c], + hash); + + /* Scale back estimate by command's rate */ + entropy *= entropy_cmds[c].rate; + + /* Upper bound of entropy is SHA_DIGEST_LENGTH */ + if (entropy > SHA_DIGEST_LENGTH) + entropy = SHA_DIGEST_LENGTH; + + /* Stir it in */ + RAND_add(hash, sizeof(hash), entropy); + + debug3("Got %0.2f bytes of entropy from '%s'", + entropy, entropy_cmds[c].cmdstring); + + total_entropy += entropy; + + /* Execution time should be a bit unpredictable */ + total_entropy += stir_gettimeofday(0.05); + total_entropy += stir_clock(0.05); + total_entropy += stir_rusage(RUSAGE_SELF, 0.1); + total_entropy += stir_rusage(RUSAGE_CHILDREN, 0.1); + } else { + debug2("Command '%s' disabled (badness %d)", + entropy_cmds[c].cmdstring, + entropy_cmds[c].badness); + + if (entropy_cmds[c].badness > 0) + entropy_cmds[c].badness--; + } + } + + return total_entropy; +} + +/* + * prng seedfile functions + */ +int +prng_check_seedfile(char *filename) +{ + struct stat st; + + /* + * XXX raceable: eg replace seed between this stat and subsequent + * open. Not such a problem because we don't really trust the + * seed file anyway. + * XXX: use secure path checking as elsewhere in OpenSSH + */ + if (lstat(filename, &st) == -1) { + /* Give up on hard errors */ + if (errno != ENOENT) + debug("WARNING: Couldn't stat random seed file " + "\"%.100s\": %s", filename, strerror(errno)); + return 0; + } + + /* regular file? */ + if (!S_ISREG(st.st_mode)) + fatal("PRNG seedfile %.100s is not a regular file", + filename); + + /* mode 0600, owned by root or the current user? */ + if (((st.st_mode & 0177) != 0) || !(st.st_uid == getuid())) { + debug("WARNING: PRNG seedfile %.100s must be mode 0600, " + "owned by uid %d", filename, getuid()); + return 0; + } + + return 1; +} + +void +prng_write_seedfile(void) +{ + int fd; + char seed[SEED_FILE_SIZE], filename[MAXPATHLEN]; + struct passwd *pw; + + pw = getpwuid(getuid()); + if (pw == NULL) + fatal("Couldn't get password entry for current user " + "(%i): %s", getuid(), strerror(errno)); + + /* Try to ensure that the parent directory is there */ + snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir, + _PATH_SSH_USER_DIR); + mkdir(filename, 0700); + + snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir, + SSH_PRNG_SEED_FILE); + + debug("writing PRNG seed to file %.100s", filename); + + RAND_bytes(seed, sizeof(seed)); + + /* Don't care if the seed doesn't exist */ + prng_check_seedfile(filename); + + if ((fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0600)) == -1) { + debug("WARNING: couldn't access PRNG seedfile %.100s " + "(%.100s)", filename, strerror(errno)); + } else { + if (atomicio(write, fd, &seed, sizeof(seed)) < sizeof(seed)) + fatal("problem writing PRNG seedfile %.100s " + "(%.100s)", filename, strerror(errno)); + close(fd); + } +} + +void +prng_read_seedfile(void) +{ + int fd; + char seed[SEED_FILE_SIZE], filename[MAXPATHLEN]; + struct passwd *pw; + + pw = getpwuid(getuid()); + if (pw == NULL) + fatal("Couldn't get password entry for current user " + "(%i): %s", getuid(), strerror(errno)); + + snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir, + SSH_PRNG_SEED_FILE); + + debug("loading PRNG seed from file %.100s", filename); + + if (!prng_check_seedfile(filename)) { + verbose("Random seed file not found or invalid, ignoring."); + return; + } + + /* open the file and read in the seed */ + fd = open(filename, O_RDONLY); + if (fd == -1) + fatal("could not open PRNG seedfile %.100s (%.100s)", + filename, strerror(errno)); + + if (atomicio(read, fd, &seed, sizeof(seed)) < sizeof(seed)) { + verbose("invalid or short read from PRNG seedfile " + "%.100s - ignoring", filename); + memset(seed, '\0', sizeof(seed)); + } + close(fd); + + /* stir in the seed, with estimated entropy zero */ + RAND_add(&seed, sizeof(seed), 0.0); +} + + +/* + * entropy command initialisation functions + */ +int +prng_read_commands(char *cmdfilename) +{ + char cmd[SEED_FILE_SIZE], *cp, line[1024], path[SEED_FILE_SIZE]; + double est; + entropy_cmd_t *entcmd; + FILE *f; + int cur_cmd, linenum, num_cmds, arg; + + if ((f = fopen(cmdfilename, "r")) == NULL) { + fatal("couldn't read entropy commands file %.100s: %.100s", + cmdfilename, strerror(errno)); + } + + num_cmds = 64; + entcmd = xmalloc(num_cmds * sizeof(entropy_cmd_t)); + memset(entcmd, '\0', num_cmds * sizeof(entropy_cmd_t)); + + /* Read in file */ + cur_cmd = linenum = 0; + while (fgets(line, sizeof(line), f)) { + linenum++; + + /* Skip leading whitespace, blank lines and comments */ + cp = line + strspn(line, WHITESPACE); + if ((*cp == 0) || (*cp == '#')) + continue; /* done with this line */ + + /* + * The first non-whitespace char should be a double quote + * delimiting the commandline + */ + if (*cp != '"') { + error("bad entropy command, %.100s line %d", + cmdfilename, linenum); + continue; + } + + /* + * First token, command args (incl. argv[0]) in double + * quotes + */ + cp = strtok(cp, "\""); + if (cp == NULL) { + error("missing or bad command string, %.100s " + "line %d -- ignored", cmdfilename, linenum); + continue; + } + strlcpy(cmd, cp, sizeof(cmd)); + + /* Second token, full command path */ + if ((cp = strtok(NULL, WHITESPACE)) == NULL) { + error("missing command path, %.100s " + "line %d -- ignored", cmdfilename, linenum); + continue; + } + + /* Did configure mark this as dead? */ + if (strncmp("undef", cp, 5) == 0) + continue; + + strlcpy(path, cp, sizeof(path)); + + /* Third token, entropy rate estimate for this command */ + if ((cp = strtok(NULL, WHITESPACE)) == NULL) { + error("missing entropy estimate, %.100s " + "line %d -- ignored", cmdfilename, linenum); + continue; + } + est = strtod(cp, NULL); + + /* end of line */ + if ((cp = strtok(NULL, WHITESPACE)) != NULL) { + error("garbage at end of line %d in %.100s " + "-- ignored", linenum, cmdfilename); + continue; + } + + /* save the command for debug messages */ + entcmd[cur_cmd].cmdstring = xstrdup(cmd); + + /* split the command args */ + cp = strtok(cmd, WHITESPACE); + arg = 0; + do { + entcmd[cur_cmd].args[arg] = xstrdup(cp); + arg++; + } while(arg < NUM_ARGS && (cp = strtok(NULL, WHITESPACE))); + + if (strtok(NULL, WHITESPACE)) + error("ignored extra commands (max %d), %.100s " + "line %d", NUM_ARGS, cmdfilename, linenum); + + /* Copy the command path and rate estimate */ + entcmd[cur_cmd].path = xstrdup(path); + entcmd[cur_cmd].rate = est; + + /* Initialise other values */ + entcmd[cur_cmd].sticky_badness = 1; + + cur_cmd++; + + /* + * If we've filled the array, reallocate it twice the size + * Do this now because even if this we're on the last + * command we need another slot to mark the last entry + */ + if (cur_cmd == num_cmds) { + num_cmds *= 2; + entcmd = xrealloc(entcmd, num_cmds * + sizeof(entropy_cmd_t)); + } + } + + /* zero the last entry */ + memset(&entcmd[cur_cmd], '\0', sizeof(entropy_cmd_t)); + + /* trim to size */ + entropy_cmds = xrealloc(entcmd, (cur_cmd + 1) * + sizeof(entropy_cmd_t)); + + debug("Loaded %d entropy commands from %.100s", cur_cmd, + cmdfilename); + + return cur_cmd < MIN_ENTROPY_SOURCES ? -1 : 0; +} + +void +usage(void) +{ + fprintf(stderr, "Usage: %s [options]\n", __progname); + fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); + fprintf(stderr, " Multiple -v increases verbosity.\n"); + fprintf(stderr, " -x Force output in hexidecimal (for debugging)\n"); + fprintf(stderr, " -X Force output in binary\n"); + fprintf(stderr, " -b bytes Number of bytes to output (default %d)\n", + OUTPUT_SEED_SIZE); +} + +int +main(int argc, char **argv) +{ + unsigned char *buf; + int ret, ch, debug_level, output_hex, bytes; + extern char *optarg; + LogLevel ll; + + __progname = get_progname(argv[0]); + log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + + ll = SYSLOG_LEVEL_INFO; + debug_level = output_hex = 0; + bytes = OUTPUT_SEED_SIZE; + + /* Don't write binary data to a tty, unless we are forced to */ + if (isatty(STDOUT_FILENO)) + output_hex = 1; + + while ((ch = getopt(argc, argv, "vxXhb:")) != -1) { + switch (ch) { + case 'v': + if (debug_level < 3) + ll = SYSLOG_LEVEL_DEBUG1 + debug_level++; + break; + case 'x': + output_hex = 1; + break; + case 'X': + output_hex = 0; + break; + case 'b': + if ((bytes = atoi(optarg)) <= 0) + fatal("Invalid number of output bytes"); + break; + case 'h': + usage(); + exit(0); + default: + error("Invalid commandline option"); + usage(); + } + } + + log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); + +#ifdef USE_SEED_FILES + prng_read_seedfile(); +#endif + + buf = xmalloc(bytes); + + /* + * Seed the RNG from wherever we can + */ + + /* Take whatever is on the stack, but don't credit it */ + RAND_add(buf, bytes, 0); + + debug("Seeded RNG with %i bytes from system calls", + (int)stir_from_system()); + +#ifdef PRNGD_PORT + if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == -1) + fatal("Entropy collection failed"); + RAND_add(buf, bytes, bytes); +#elif defined(PRNGD_SOCKET) + if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == -1) + fatal("Entropy collection failed"); + RAND_add(buf, bytes, bytes); +#else + /* Read in collection commands */ + if (prng_read_commands(SSH_PRNG_COMMAND_FILE) == -1) + fatal("PRNG initialisation failed -- exiting."); + debug("Seeded RNG with %i bytes from programs", + (int)stir_from_programs()); +#endif + +#ifdef USE_SEED_FILES + prng_write_seedfile(); +#endif + + /* + * Write the seed to stdout + */ + + if (!RAND_status()) + fatal("Not enough entropy in RNG"); + + RAND_bytes(buf, bytes); + + if (output_hex) { + for(ret = 0; ret < bytes; ret++) + printf("%02x", (unsigned char)(buf[ret])); + printf("\n"); + } else + ret = atomicio(write, STDOUT_FILENO, buf, bytes); + + memset(buf, '\0', bytes); + xfree(buf); + + return ret == bytes ? 0 : 1; +} + Index: src/crypto/openssh/ssh-rsa.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-rsa.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh-rsa.c --- src/crypto/openssh/ssh-rsa.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh-rsa.c 30 Jun 2002 11:38:01 -0000 @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-rsa.c,v 1.8 2001/03/27 10:57:00 markus Exp $"); +RCSID("$OpenBSD: ssh-rsa.c,v 1.21 2002/06/23 03:30:17 deraadt Exp $"); #include #include @@ -35,17 +35,16 @@ #include "key.h" #include "ssh-rsa.h" #include "compat.h" +#include "ssh.h" /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int -ssh_rsa_sign( - Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen) +ssh_rsa_sign(Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { const EVP_MD *evp_md; EVP_MD_CTX md; - u_char *digest, *sig, *ret; + u_char digest[EVP_MAX_MD_SIZE], *sig, *ret; u_int slen, dlen, len; int ok, nid; Buffer b; @@ -59,32 +58,30 @@ error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); return -1; } - dlen = evp_md->md_size; - digest = xmalloc(dlen); EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, NULL); + EVP_DigestFinal(&md, digest, &dlen); slen = RSA_size(key->rsa); sig = xmalloc(slen); ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); - memset(digest, 'd', dlen); - xfree(digest); + memset(digest, 'd', sizeof(digest)); if (ok != 1) { int ecode = ERR_get_error(); - error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL)); + error("ssh_rsa_sign: RSA_sign failed: %s", + ERR_error_string(ecode, NULL)); xfree(sig); return -1; } if (len < slen) { int diff = slen - len; - debug("slen %d > len %d", slen, len); + debug("slen %u > len %u", slen, len); memmove(sig + diff, sig, len); memset(sig, 0, diff); } else if (len > slen) { - error("ssh_rsa_sign: slen %d slen2 %d", slen, len); + error("ssh_rsa_sign: slen %u slen2 %u", slen, len); xfree(sig); return -1; } @@ -103,35 +100,32 @@ *lenp = len; if (sigp != NULL) *sigp = ret; - debug2("ssh_rsa_sign: done"); return 0; } int -ssh_rsa_verify( - Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen) +ssh_rsa_verify(Key *key, u_char *signature, u_int signaturelen, + u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; - u_char *sigblob, *digest; - u_int len, dlen; + u_char digest[EVP_MAX_MD_SIZE], *sigblob; + u_int len, dlen, modlen; int rlen, ret, nid; if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { error("ssh_rsa_verify: no RSA key"); return -1; } - if (BN_num_bits(key->rsa->n) < 768) { - error("ssh_rsa_verify: n too small: %d bits", - BN_num_bits(key->rsa->n)); + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", + BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } buffer_init(&b); - buffer_append(&b, (char *) signature, signaturelen); + buffer_append(&b, signature, signaturelen); ktype = buffer_get_string(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { error("ssh_rsa_verify: cannot handle type %s", ktype); @@ -140,34 +134,47 @@ return -1; } xfree(ktype); - sigblob = (u_char *)buffer_get_string(&b, &len); + sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); - if(rlen != 0) { - xfree(sigblob); + if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); + xfree(sigblob); return -1; } + /* RSA_verify expects a signature of RSA_size */ + modlen = RSA_size(key->rsa); + if (len > modlen) { + error("ssh_rsa_verify: len %u > modlen %u", len, modlen); + xfree(sigblob); + return -1; + } else if (len < modlen) { + int diff = modlen - len; + debug("ssh_rsa_verify: add padding: modlen %u > len %u", + modlen, len); + sigblob = xrealloc(sigblob, modlen); + memmove(sigblob + diff, sigblob, len); + memset(sigblob, 0, diff); + len = modlen; + } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - xfree(sigblob); error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); + xfree(sigblob); return -1; } - dlen = evp_md->md_size; - digest = xmalloc(dlen); EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, NULL); + EVP_DigestFinal(&md, digest, &dlen); ret = RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); - memset(digest, 'd', dlen); - xfree(digest); + memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); xfree(sigblob); if (ret == 0) { int ecode = ERR_get_error(); - error("ssh_rsa_verify: RSA_verify failed: %s", ERR_error_string(ecode, NULL)); + error("ssh_rsa_verify: RSA_verify failed: %s", + ERR_error_string(ecode, NULL)); } debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; Index: src/crypto/openssh/ssh-rsa.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh-rsa.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh-rsa.h --- src/crypto/openssh/ssh-rsa.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh-rsa.h 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.h,v 1.3 2001/01/29 01:58:18 niklas Exp $ */ +/* $OpenBSD: ssh-rsa.h,v 1.6 2002/02/24 19:14:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -26,16 +26,7 @@ #ifndef SSH_RSA_H #define SSH_RSA_H -int -ssh_rsa_sign( - Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen); - -int -ssh_rsa_verify( - Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen); +int ssh_rsa_sign(Key *, u_char **, u_int *, u_char *, u_int); +int ssh_rsa_verify(Key *, u_char *, u_int, u_char *, u_int); #endif Index: src/crypto/openssh/ssh.1 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh.1,v retrieving revision 1.4.2.8 diff -u -u -r1.4.2.8 ssh.1 --- src/crypto/openssh/ssh.1 28 Sep 2001 01:33:35 -0000 1.4.2.8 +++ src/crypto/openssh/ssh.1 30 Jun 2002 11:38:01 -0000 @@ -34,9 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.107 2001/04/22 23:58:36 markus Exp $ -.\" $FreeBSD: src/crypto/openssh/ssh.1,v 1.4.2.8 2001/09/28 01:33:35 green Exp $ -.\" +.\" $OpenBSD: ssh.1,v 1.160 2002/06/22 11:51:39 naddy Exp $ +.\" $FreeBSD: src/crypto/openssh/ssh.1,v 1.24 2002/06/29 11:48:58 des Exp $ .Dd September 25, 1999 .Dt SSH 1 .Os @@ -46,11 +45,12 @@ .Sh SYNOPSIS .Nm ssh .Op Fl l Ar login_name -.Op Ar hostname | user@hostname +.Ar hostname | user@hostname .Op Ar command .Pp .Nm ssh .Op Fl afgknqstvxACNPTX1246 +.Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Op Fl e Ar escape_char .Op Fl i Ar identity_file @@ -58,6 +58,7 @@ .Op Fl m Ar mac_spec .Op Fl o Ar option .Op Fl p Ar port +.Op Fl F Ar configfile .Oo Fl L Xo .Sm off .Ar port : @@ -74,7 +75,8 @@ .Sm on .Xc .Oc -.Op Ar hostname | user@hostname +.Op Fl D Ar port +.Ar hostname | user@hostname .Op Ar command .Sh DESCRIPTION .Nm @@ -206,16 +208,14 @@ .Pp .Ss SSH protocol version 2 .Pp -When a user connects using the protocol version 2 -different authentication methods are available. +When a user connects using protocol version 2 +similar authentication methods are available. Using the default values for .Cm PreferredAuthentications , -the client will try to authenticate first using the public key method; -if this method fails password authentication is attempted, -and finally if this method fails keyboard-interactive authentication -is attempted. -If this method fails password authentication is -tried. +the client will try to authenticate first using the hostbased method; +if this method fails public key authentication is attempted, +and finally if this method fails keyboard-interactive and +password authentication are tried. .Pp The public key method is similar to RSA authentication described in the previous section and allows the RSA or DSA algorithm to be used: @@ -225,7 +225,7 @@ .Pa $HOME/.ssh/id_rsa , to sign the session identifier and sends the result to the server. The server checks whether the matching public key is listed in -.Pa $HOME/.ssh/authorized_keys2 +.Pa $HOME/.ssh/authorized_keys and grants access if both the key is found and the signature is correct. The session identifier is derived from a shared Diffie-Hellman value and is only known to the client and the server. @@ -270,16 +270,16 @@ .Ss Escape Characters .Pp When a pseudo terminal has been requested, ssh supports a number of functions -through the use of an escape character. +through the use of an escape character. .Pp A single tilde character can be sent as .Ic ~~ -(or by following the tilde by a character other than those described above). +or by following the tilde by a character other than those described below. The escape character must always follow a newline to be interpreted as special. The escape character can be changed in configuration files using the .Cm EscapeChar -configuration directive or on the command line by the +configuration directive or on the command line by the .Fl e option. .Pp @@ -295,9 +295,15 @@ List forwarded connections .It Cm ~& Background ssh at logout when waiting for forwarded connection / X11 sessions -to terminate (protocol version 1 only) +to terminate .It Cm ~? Display a list of escape characters +.It Cm ~C +Open command line (only useful for adding port forwardings using the +.Fl L +and +.Fl R +options) .It Cm ~R Request rekeying of the connection (only useful for SSH protocol version 2 and if the peer supports it) @@ -305,18 +311,27 @@ .Pp .Ss X11 and TCP forwarding .Pp -If the user is using X11 (the +If the +.Cm ForwardX11 +variable is set to +.Dq yes +(or, see the description of the +.Fl X +and +.Fl x +options described later) +and the user is using X11 (the .Ev DISPLAY -environment variable is set), the connection to the X11 display can -be forwarded to the remote side in such a way that any X11 +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 .Ev DISPLAY . -Forwarding of X11 connections weakens the security of ssh and is -disabled by default. X11 forwarding can be enabled on the command line -or in configuration files. +Forwarding of X11 connections can be +configured on the command line or in configuration files. +Take note that X11 forwarding can represent a security hazard. .Pp The .Ev DISPLAY @@ -342,10 +357,10 @@ .Pp 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. +the command line or in a configuration file. .Pp Forwarding of arbitrary TCP/IP connections over the secure channel can -be specified either on command line or in a configuration file. +be specified either on the 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 through firewalls. .Pp @@ -354,17 +369,12 @@ .Nm automatically maintains and checks a database containing identifications for all hosts it has ever been used with. -RSA host keys are stored in +Host keys are stored in .Pa $HOME/.ssh/known_hosts -and -host keys used in the protocol version 2 are stored in -.Pa $HOME/.ssh/known_hosts2 in the user's home directory. -Additionally, the files +Additionally, the file .Pa /etc/ssh/ssh_known_hosts -and -.Pa /etc/ssh/ssh_known_hosts2 -are automatically checked for 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, @@ -376,7 +386,7 @@ otherwise be used to circumvent the encryption. The .Cm StrictHostKeyChecking -option (see below) can be used to prevent logins to machines whose +option can be used to prevent logins to machines whose host key is not known or has changed. .Pp The options are as follows: @@ -386,20 +396,27 @@ .It Fl A Enables forwarding of the authentication agent connection. This can also be specified on a per-host basis in a configuration file. -.It Fl c Ar blowfish|3des +.It Fl b Ar bind_address +Specify the interface to transmit from on machines with multiple +interfaces or aliased addresses. +.It Fl c Ar blowfish|3des|des Selects the cipher to use for encrypting the session. .Ar 3des is used by default. It is believed to be secure. .Ar 3des (triple-des) is an encrypt-decrypt-encrypt triple with three different keys. -It is presumably more secure than the -.Ar des -cipher which is no longer fully supported in -.Nm ssh . .Ar blowfish is a fast block cipher, it appears very secure and is much faster than .Ar 3des . +.Ar des +is only supported in the +.Nm +client for interoperability with legacy protocol 1 implementations +that do not support the +.Ar 3des +cipher. Its use is strongly discouraged due to cryptographic +weaknesses. .It Fl c Ar cipher_spec Additionally, for protocol version 2 a comma-separated list of ciphers can be specified in order of preference. @@ -434,17 +451,27 @@ .It Fl g Allows remote hosts to connect to local forwarded ports. .It Fl i Ar identity_file -Selects the file from which the identity (private key) for +Selects a file from which the identity (private key) for RSA or DSA authentication is read. -Default is +The default is .Pa $HOME/.ssh/identity -in the user's home directory. +for protocol version 1, and +.Pa $HOME/.ssh/id_rsa +and +.Pa $HOME/.ssh/id_dsa +for protocol version 2. Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple .Fl i options (and multiple identities specified in configuration files). +.It Fl I Ar smartcard_device +Specifies which smartcard device to use. The argument is +the device +.Nm +should use to communicate with a smartcard used for storing the user's +private RSA key. .It Fl k Disables forwarding of Kerberos tickets and AFS tokens. This may also be specified on a per-host basis in the configuration file. @@ -480,20 +507,19 @@ option.) .It Fl N Do not execute a remote command. -This is useful if you just want to forward ports +This is useful for just forwarding ports (protocol version 2 only). .It Fl o Ar option -Can be used to give options in the format used in the config file. +Can be used to give options in the format used in the configuration 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. .It Fl p Ar port Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file. .It Fl P Use a non-privileged port for outgoing connections. -This can be used if your firewall does +This can be used if a firewall does not permit connections from privileged ports. Note that this option turns off .Cm RhostsAuthentication @@ -503,10 +529,9 @@ .It Fl q Quiet mode. Causes all warning and diagnostic messages to be suppressed. -Only fatal errors are displayed. .It Fl s -May be used to request invocation of a subsystem on the remote system. Subsystems are a feature of the SSH2 protocol which facilitate the use -of SSH as a secure transport for other application (eg. sftp). The +May be used to request invocation of a subsystem on the remote system. Subsystems are a feature of the SSH2 protocol which facilitate the use +of SSH as a secure transport for other applications (eg. sftp). The subsystem is specified as the remote command. .It Fl t Force pseudo-tty allocation. @@ -545,13 +570,21 @@ .Dq level can be controlled by the .Cm CompressionLevel -option (see below). +option. 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 -.Cm Compress -option below. +.Cm Compression +option. +.It Fl F Ar configfile +Specifies an alternative per-user configuration file. +If a configuration file is given on the command line, +the system-wide configuration file +.Pq Pa /etc/ssh/ssh_config +will be ignored. +The default for the per-user configuration file is +.Pa $HOME/.ssh/config . .It Fl L Ar 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. @@ -585,6 +618,20 @@ logging in as root on the remote machine. IPv6 addresses can be specified with an alternative syntax: .Ar port/host/hostport +.It Fl D Ar port +Specifies a local +.Dq dynamic +application-level port forwarding. +This works by allocating a socket to listen to +.Ar port +on the local side, and whenever a connection is made to this port, the +connection is forwarded over the secure channel, and the application +protocol is then used to determine where to connect to from the +remote machine. Currently the SOCKS4 protocol is supported, and +.Nm +will act as a SOCKS4 server. +Only root can forward privileged ports. +Dynamic port forwardings can also be specified in the configuration file. .It Fl 1 Forces .Nm @@ -604,509 +651,10 @@ .El .Sh CONFIGURATION FILES .Nm -obtains configuration data from the following sources (in this order): -command line options, user's configuration file -.Pq Pa $HOME/.ssh/config , -and system-wide configuration file -.Pq Pa /etc/ssh/ssh_config . -For each parameter, the first obtained value -will be used. -The configuration files contain sections bracketed by -.Dq 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. -.Pp -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. -.Pp -The configuration file has the following format: -.Pp -Empty lines and lines starting with -.Ql # -are comments. -.Pp -Otherwise a line is of the format -.Dq keyword arguments . -The possible -keywords and their meanings are as follows (note that the -configuration files are case-sensitive): -.Bl -tag -width Ds -.It Cm Host -Restricts the following declarations (up to the next -.Cm Host -keyword) to be only for those hosts that match one of the patterns -given after the keyword. -.Ql \&* -and -.Ql ? -can be used as wildcards in the -patterns. -A single -.Ql \&* -as a pattern can be used to provide global -defaults for all hosts. -The host is the -.Ar hostname -argument given on the command line (i.e., the name is not converted to -a canonicalized host name before matching). -.It Cm AFSTokenPassing -Specifies whether to pass AFS tokens to remote host. -The argument to this keyword must be -.Dq yes -or -.Dq no . -This option applies to protocol version 1 only. -.It Cm BatchMode -If set to -.Dq 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 -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm CheckHostIP -If this flag is set to -.Dq yes , -ssh will additionally check the host IP address in the -.Pa known_hosts -file. -This allows ssh to detect if a host key changed due to DNS spoofing. -If the option is set to -.Dq no , -the check will not be executed. -The default is -.Dq yes . -.It Cm Cipher -Specifies the cipher to use for encrypting the session -in protocol version 1. -Currently, -.Dq blowfish -and -.Dq 3des -are supported. -The default is -.Dq 3des . -.It Cm Ciphers -Specifies the ciphers allowed for protocol version 2 -in order of preference. -Multiple ciphers must be comma-separated. -The default is -.Pp -.Bd -literal - ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, - aes192-cbc,aes256-cbc'' -.Ed -.It Cm Compression -Specifies whether to use compression. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm CompressionLevel -Specifies the compression level to use if compression is enabled. -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 -.Xr gzip 1 . -Note that this option applies to protocol version 1 only. -.It Cm 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. -The default is 4. -.It Cm EscapeChar -Sets the escape character (default: -.Ql ~ ) . -The escape character can also -be set on the command line. -The argument should be a single character, -.Ql ^ -followed by a letter, or -.Dq none -to disable the escape -character entirely (making the connection transparent for binary -data). -.It Cm FallBackToRsh -Specifies that if connecting via -.Nm -fails due to a connection refused error (there is no -.Xr sshd 8 -listening on the remote host), -.Xr rsh 1 -should automatically be used instead (after a suitable warning about -the session being unencrypted). -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm ForwardAgent -Specifies whether the connection to the authentication agent (if any) -will be forwarded to the remote machine. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm ForwardX11 -Specifies whether X11 connections will be automatically redirected -over the secure channel and -.Ev DISPLAY -set. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm GatewayPorts -Specifies whether remote hosts are allowed to connect to local -forwarded ports. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm GlobalKnownHostsFile -Specifies a file to use for the protocol version 1 global -host key database instead of -.Pa /etc/ssh/ssh_known_hosts . -.It Cm GlobalKnownHostsFile2 -Specifies a file to use for the protocol version 2 global -host key database instead of -.Pa /etc/ssh/ssh_known_hosts2 . -.It Cm HostbasedAuthentication -Specifies whether to try rhosts based authentication with public key -authentication. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq yes . -This option applies to protocol version 2 only and -is similar to -.Cm RhostsRSAAuthentication . -.It Cm HostKeyAlgorithms -Specfies the protocol version 2 host key algorithms -that the client wants to use in order of preference. -The default for this option is: -.Dq ssh-rsa,ssh-dss -.It Cm HostKeyAlias -Specifies an alias that should be used instead of the -real host name when looking up or saving the host key -in the host key database files. -This option is useful for tunneling ssh connections -or if you have multiple servers running on a single host. -.It Cm HostName -Specifies the real host name to log into. -This can be used to specify nicknames 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 -.Cm HostName -specifications). -.It Cm IdentityFile -Specifies the file from which the user's RSA or DSA authentication identity -is read (default -.Pa $HOME/.ssh/identity -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. -.It Cm 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. -.Pp -The default is -.Dq 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. -.Pp -To disable keepalives, the value should be set to -.Dq no -in both the server and the client configuration files. -.It Cm KerberosAuthentication -Specifies whether Kerberos authentication will be used. -The argument to this keyword must be -.Dq yes -or -.Dq no . -.It Cm KerberosTgtPassing -Specifies whether a Kerberos TGT will be forwarded to the server. -This will only work if the Kerberos server is actually an AFS kaserver. -The argument to this keyword must be -.Dq yes -or -.Dq no . -.It Cm 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 superuser can forward privileged ports. -.It Cm LogLevel -Gives the verbosity level that is used when logging messages from -.Nm ssh . -The possible values are: -QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG. -The default is INFO. -.It Cm MACs -Specifies the MAC (message authentication code) algorithms -in order of preference. -The MAC algorithm is used in protocol version 2 -for data integrity protection. -Multiple algorithms must be comma-separated. -The default is -.Pp -.Bd -literal - ``hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripemd160@openssh.com, - hmac-sha1-96,hmac-md5-96'' -.Ed -.It Cm NumberOfPasswordPrompts -Specifies the number of password prompts before giving up. -The argument to this keyword must be an integer. -Default is 3. -.It Cm PasswordAuthentication -Specifies whether to use password authentication. -The argument to this keyword must be -.Dq yes -or -.Dq no . -The default is -.Dq yes . -.It Cm Port -Specifies the port number to connect on the remote host. -Default is 22. -.It Cm PreferredAuthentications -Specifies the order in which the client should try protocol 2 -authentication methods. This allows a client to prefer one method (e.g. -.Cm keyboard-interactive ) -over another method (e.g. -.Cm password ) -The default for this option is: -.Dq publickey, password, keyboard-interactive -.It Cm Protocol -Specifies the protocol versions -.Nm -should support in order of preference. -The possible values are -.Dq 1 -and -.Dq 2 . -Multiple versions must be comma-separated. -The default is -.Dq 2,1 . -This means that -.Nm -tries version 2 and falls back to version 1 -if version 2 is not available. -.It Cm 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 -.Pa /bin/sh . -In the command string, -.Ql %h -will be substituted by the host name to -connect and -.Ql %p -by the port. -The command can be basically anything, -and should read from its standard input and write to its standard output. -It should eventually connect an -.Xr sshd 8 -server running on some machine, or execute -.Ic 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 -.Cm CheckHostIP -is not available for connects with a proxy command. -.Pp -.It Cm PubkeyAuthentication -Specifies whether to try public key authentication. -The argument to this keyword must be -.Dq yes -or -.Dq no . -The default is -.Dq yes . -This option applies to protocol version 2 only. -.It Cm 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 superuser can forward privileged ports. -.It Cm 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 -.Cm RhostsRSAAuthentication ). -The argument to this keyword must be -.Dq yes -or -.Dq no . -The default is -.Dq yes . -This option applies to protocol version 1 only. -.It Cm RhostsRSAAuthentication -Specifies whether to try rhosts based authentication with RSA host -authentication. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq yes . -This option applies to protocol version 1 only. -.It Cm RSAAuthentication -Specifies whether to try RSA authentication. -The argument to this keyword must be -.Dq yes -or -.Dq no . -RSA authentication will only be -attempted if the identity file exists, or an authentication agent is -running. -The default is -.Dq yes . -Note that this option applies to protocol version 1 only. -.It Cm ChallengeResponseAuthentication -Specifies whether to use challenge response authentication. -Currently there is only support for -.Xr skey 1 -authentication. -The argument to this keyword must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm StrictHostKeyChecking -If this flag is set to -.Dq yes , -.Nm -will never automatically add host keys to the -.Pa $HOME/.ssh/known_hosts -and -.Pa $HOME/.ssh/known_hosts2 -files, and refuses to connect to 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 -.Pa /etc/ssh/ssh_known_hosts -and -.Pa /etc/ssh/ssh_known_hosts2 -files installed and frequently -connect to new hosts. -This option forces the user to manually -add all new hosts. -If this flag is set to -.Dq no , -.Nm -will automatically add new host keys to the -user known hosts files. -If this flag is set to -.Dq ask , -new host keys -will be added to the user known host files only after the user -has confirmed that is what they really want to do, and -.Nm -will refuse to connect to hosts whose host key has changed. -The host keys of -known hosts will be verified automatically in all cases. -The argument must be -.Dq yes , -.Dq no -or -.Dq ask . -The default is -.Dq ask . -.It Cm UsePrivilegedPort -Specifies whether to use a privileged port for outgoing connections. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -Note that you need to set this option to -.Dq yes -if you want to use -.Cm RhostsAuthentication -and -.Cm RhostsRSAAuthentication -with older servers. -.It Cm User -Specifies the user to log in as. -This can be useful if you have a different user name on different machines. -This saves the trouble of -having to remember to give the user name on the command line. -.It Cm UserKnownHostsFile -Specifies a file to use for the protocol version 1 user -host key database instead of -.Pa $HOME/.ssh/known_hosts . -.It Cm UserKnownHostsFile2 -Specifies a file to use for the protocol version 2 user -host key database instead of -.Pa $HOME/.ssh/known_hosts2 . -.It Cm UseRsh -Specifies that rlogin/rsh should be used for this host. -It is possible that the host does not at all support the -.Nm -protocol. -This causes -.Nm -to immediately execute -.Xr rsh 1 . -All other options (except -.Cm HostName ) -are ignored if this has been specified. -The argument must be -.Dq yes -or -.Dq no . -.It Cm XAuthLocation -Specifies the location of the -.Xr xauth 1 -program. -The default is -.Pa /usr/X11R6/bin/xauth . -.El +may additionally obtain configuration data from +a per-user configuration file and a system-wide configuration file. +The file format and configuration options are described in +.Xr ssh_config 5 . .Sh ENVIRONMENT .Nm will normally set the following environment variables: @@ -1136,14 +684,37 @@ .Ev USER ; set for compatibility with systems that use this variable. .It Ev MAIL -Set to point the user's mailbox. +Set to the path of the user's mailbox. .It Ev PATH Set to the default .Ev PATH , as specified when compiling .Nm ssh . +.It Ev SSH_ASKPASS +If +.Nm +needs a passphrase, it will read the passphrase from the current +terminal if it was run from a terminal. +If +.Nm +does not have a terminal associated with it but +.Ev DISPLAY +and +.Ev SSH_ASKPASS +are set, it will execute the program specified by +.Ev SSH_ASKPASS +and open an X11 window to read the passphrase. +This is particularly useful when calling +.Nm +from a +.Pa .Xsession +or related script. +(Note that on some machines it +may be necessary to redirect the input from +.Pa /dev/null +to make this work.) .It Ev SSH_AUTH_SOCK -indicates the path of a unix-domain socket used to communicate with the +Identifies the path of a unix-domain socket used to communicate with the agent. .It Ev SSH_CLIENT Identifies the client end of the connection. @@ -1176,13 +747,10 @@ to the environment. .Sh FILES .Bl -tag -width Ds -.It Pa $HOME/.ssh/known_hosts, $HOME/.ssh/known_hosts2 -Records host keys for all hosts the user has logged into (that are not +.It Pa $HOME/.ssh/known_hosts +Records host keys for all hosts the user has logged into that are not in -.Pa /etc/ssh/ssh_known_hosts -for protocol version 1 or -.Pa /etc/ssh/ssh_known_hosts2 -for protocol version 2). +.Pa /etc/ssh/ssh_known_hosts . See .Xr sshd 8 . .It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa @@ -1205,15 +773,15 @@ file should be added to .Pa $HOME/.ssh/authorized_keys on all machines -where you wish to log in using protocol version 1 RSA authentication. +where the user wishes to log in using protocol version 1 RSA authentication. The contents of the .Pa $HOME/.ssh/id_dsa.pub and .Pa $HOME/.ssh/id_rsa.pub file should be added to -.Pa $HOME/.ssh/authorized_keys2 +.Pa $HOME/.ssh/authorized_keys on all machines -where you wish to log in using protocol version 2 DSA/RSA authentication. +where the user wishes to log in using protocol version 2 DSA/RSA authentication. These files are not sensitive and can (but need not) be readable by anyone. These files are @@ -1221,42 +789,26 @@ the convenience of the user. .It Pa $HOME/.ssh/config This is the per-user configuration file. -The format of this file is described above. -This file is used by the -.Nm -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. +The file format and configuration options are described in +.Xr ssh_config 5 . .It Pa $HOME/.ssh/authorized_keys -Lists the RSA keys that can be used for logging in as this user. +Lists the public keys (RSA/DSA) that can be used for logging in as this user. The format of this file is described in the .Xr sshd 8 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). +identity files. This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. -.It Pa $HOME/.ssh/authorized_keys2 -Lists the public keys (RSA/DSA) that can be used for logging in as this user. -This file is not highly sensitive, but the recommended -permissions are read/write for the user, and not accessible by others. -.It Pa /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2 +.It Pa /etc/ssh/ssh_known_hosts Systemwide list of known host keys. -.Pa /etc/ssh/ssh_known_hosts -contains RSA and -.Pa /etc/ssh/ssh_known_hosts2 -contains RSA or DSA keys for protocol version 2. -These files should be prepared by the +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. +by spaces): system name, public key and optional comment field. When different names are used for the same machine, all such names should be listed, separated by commas. @@ -1273,10 +825,31 @@ would then be able to fool host authentication. .It Pa /etc/ssh/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. +The file format and configuration options are described in +.Xr ssh_config 5 . +.It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key +These three files contain the private parts of the host keys +and are used for +.Cm RhostsRSAAuthentication +and +.Cm HostbasedAuthentication . +If the protocol version 1 +.Cm RhostsRSAAuthentication +method is used, +.Nm +must be setuid root, since the host key is readable only by root. +For protocol version 2, +.Nm +uses +.Xr ssh-keysign 8 +to access the host keys for +.Cm HostbasedAuthentication . +This eliminates the requirement that +.Nm +be setuid root when that authentication method is used. +By default +.Nm +is not setuid root. .It Pa $HOME/.rhosts This file is used in .Pa \&.rhosts @@ -1302,9 +875,9 @@ .Xr sshd 8 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 +If the server machine does not have the client's host key in .Pa /etc/ssh/ssh_known_hosts , -you can store it in +it can be stored in .Pa $HOME/.ssh/known_hosts . The easiest way to do this is to connect back to the client from the server machine using ssh; this @@ -1317,7 +890,7 @@ having this file is to be able to use rhosts authentication with .Nm without permitting login with -.Xr rlogin 1 +.Nm rlogin or .Xr rsh 1 . .It Pa /etc/hosts.equiv @@ -1361,6 +934,10 @@ .Sx ENVIRONMENT above. .El +.Sh DIAGNOSTICS +.Nm +exits with the exit status of the remote command or with 255 +if an error occurred. .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. @@ -1371,7 +948,6 @@ Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. .Sh SEE ALSO -.Xr rlogin 1 , .Xr rsh 1 , .Xr scp 1 , .Xr sftp 1 , @@ -1379,6 +955,8 @@ .Xr ssh-agent 1 , .Xr ssh-keygen 1 , .Xr telnet 1 , +.Xr ssh_config 5 , +.Xr ssh-keysign 8 , .Xr sshd 8 .Rs .%A T. Ylonen @@ -1387,7 +965,7 @@ .%A T. Rinne .%A S. Lehtinen .%T "SSH Protocol Architecture" -.%N draft-ietf-secsh-architecture-07.txt -.%D January 2001 +.%N draft-ietf-secsh-architecture-12.txt +.%D January 2002 .%O work in progress material .Re Index: src/crypto/openssh/ssh.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh.c,v retrieving revision 1.4.2.5 diff -u -u -r1.4.2.5 ssh.c --- src/crypto/openssh/ssh.c 28 Sep 2001 01:33:35 -0000 1.4.2.5 +++ src/crypto/openssh/ssh.c 30 Jun 2002 11:38:01 -0000 @@ -13,6 +13,7 @@ * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 1999 Niels Provos. All rights reserved. + * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Modified to work with SSL by Niels Provos * in Canada (German citizen). @@ -39,8 +40,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.116 2001/04/17 12:55:04 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/ssh.c,v 1.4.2.5 2001/09/28 01:33:35 green Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.179 2002/06/12 01:09:52 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/ssh.c,v 1.21 2002/06/29 10:57:53 des Exp $"); #include #include @@ -53,7 +54,6 @@ #include "xmalloc.h" #include "packet.h" #include "buffer.h" -#include "uidswap.h" #include "channels.h" #include "key.h" #include "authfd.h" @@ -70,11 +70,23 @@ #include "mac.h" #include "sshtty.h" +#ifdef SMARTCARD +#include "scard.h" +#endif + +#ifdef HAVE___PROGNAME extern char *__progname; +#else +char *__progname; +#endif /* Flag indicating whether IPv4 or IPv6. This can be set on the command line. Default value is AF_UNSPEC means both IPv4 and IPv6. */ +#ifdef IPV4_DEFAULT +int IPv4or6 = AF_INET; +#else int IPv4or6 = AF_UNSPEC; +#endif /* Flag indicating whether debug mode is on. This can be set on the command line. */ int debug_flag = 0; @@ -95,7 +107,7 @@ /* * 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 + * so that the passphrase can be entered manually, and then ssh goes to the * background. */ int fork_after_authentication_flag = 0; @@ -106,6 +118,9 @@ */ Options options; +/* optional user configfile */ +char *config = NULL; + /* * 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 @@ -116,22 +131,12 @@ /* socket address the host resolves to */ struct sockaddr_storage hostaddr; -/* - * 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; - /* Private host keys. */ -struct { - Key **keys; - int nkeys; -} sensitive_data; +Sensitive sensitive_data; /* Original real UID. */ uid_t original_real_uid; +uid_t original_effective_uid; /* command to be executed */ Buffer command; @@ -139,24 +144,32 @@ /* Should we execute a command or invoke a subsystem? */ int subsystem_flag = 0; +/* # of replies received for global requests */ +static int client_global_request_id = 0; + /* Prints a help message to the user. This function never returns. */ -void +static void usage(void) { fprintf(stderr, "Usage: %s [options] host [command]\n", __progname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -l user Log in using this user name.\n"); fprintf(stderr, " -n Redirect input from " _PATH_DEVNULL ".\n"); + fprintf(stderr, " -F config Config file (default: ~/%s).\n", + _PATH_SSH_USER_CONFFILE); fprintf(stderr, " -A Enable authentication agent forwarding.\n"); - fprintf(stderr, " -a Disable authentication agent forwarding.\n"); + fprintf(stderr, " -a Disable authentication agent forwarding (default).\n"); #ifdef AFS fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); #endif /* AFS */ fprintf(stderr, " -X Enable X11 connection forwarding.\n"); - fprintf(stderr, " -x Disable X11 connection forwarding.\n"); + fprintf(stderr, " -x Disable X11 connection forwarding (default).\n"); fprintf(stderr, " -i file Identity for public key authentication " "(default: ~/.ssh/identity)\n"); +#ifdef SMARTCARD + fprintf(stderr, " -I reader Set smartcard reader.\n"); +#endif fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n"); fprintf(stderr, " -T Do not allocate a tty.\n"); fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); @@ -167,14 +180,14 @@ 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: " - "``3des'', ``blowfish''\n"); + fprintf(stderr, " -c cipher Select encryption algorithm\n"); fprintf(stderr, " -m macs Specify MAC algorithms for protocol version 2.\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", __progname); fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); + fprintf(stderr, " -D port Enable dynamic application-level port forwarding.\n"); fprintf(stderr, " -C Enable compression.\n"); fprintf(stderr, " -N Do not execute a shell or command.\n"); fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); @@ -184,53 +197,13 @@ fprintf(stderr, " -6 Use IPv6 only.\n"); fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n"); fprintf(stderr, " -s Invoke command (mandatory) as SSH2 subsystem.\n"); + fprintf(stderr, " -b addr Local IP address.\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) -{ - char *args[10]; - int i; - - log("Using rsh. WARNING: Connection will not be encrypted."); - /* Build argument list for rsh. */ - i = 0; -#ifndef _PATH_RSH -#define _PATH_RSH "/usr/bin/rsh" -#endif - args[i++] = _PATH_RSH; - /* host may have to come after user on some systems */ - args[i++] = host; - 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(_PATH_RSH, args); - perror(_PATH_RSH); - exit(1); -} - -int ssh_session(void); -int ssh_session2(void); -void load_public_identity_files(void); +static int ssh_session(void); +static int ssh_session2(void); +static void load_public_identity_files(void); /* * Main program for the ssh client. @@ -238,13 +211,18 @@ int main(int ac, char **av) { - int i, opt, optind, exit_status, ok; + int i, opt, exit_status; u_short fwd_port, fwd_host_port; - char *optarg, *cp, buf[256]; + char sfwd_port[6], sfwd_host_port[6]; + char *p, *cp, buf[256]; struct stat st; struct passwd *pw; int dummy; - uid_t original_effective_uid; + extern int optind, optreset; + extern char *optarg; + + __progname = get_progname(av[0]); + init_rng(); /* * Save the original real uid. It will be needed later (uid-swapping @@ -253,6 +231,7 @@ original_real_uid = getuid(); original_effective_uid = geteuid(); +#ifdef HAVE_SETRLIMIT /* If we are installed setuid root be careful to not drop core. */ if (original_real_uid != original_effective_uid) { struct rlimit rlim; @@ -260,6 +239,7 @@ if (setrlimit(RLIMIT_CORE, &rlim) < 0) fatal("setrlimit failed: %.100s", strerror(errno)); } +#endif /* Get user data. */ pw = getpwuid(original_real_uid); if (!pw) { @@ -276,7 +256,7 @@ * 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(pw); + PRIV_END; /* * Set our umask to something reasonable, as some files are created @@ -292,35 +272,9 @@ /* Parse command-line arguments. */ host = NULL; - for (optind = 1; optind < ac; optind++) { - if (av[optind][0] != '-') { - if (host) - break; - if ((cp = strchr(av[optind], '@'))) { - if(cp == av[optind]) - usage(); - options.user = av[optind]; - *cp = '\0'; - host = ++cp; - } else - host = av[optind]; - continue; - } - opt = av[optind][1]; - if (!opt) - usage(); - if (strchr("eilcmpLRDo", 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; - } +again: + while ((opt = getopt(ac, av, + "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) { switch (opt) { case '1': options.protocol = SSH_PROTO_1; @@ -361,23 +315,29 @@ break; #ifdef AFS case 'k': - options.krb4_tgt_passing = 0; -#ifdef KRB5 - options.krb5_tgt_passing = 0; -#endif + options.kerberos_tgt_passing = 0; options.afs_token_passing = 0; break; #endif case 'i': if (stat(optarg, &st) < 0) { - fprintf(stderr, "Warning: Identity file %s does not exist.\n", - optarg); + 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); + 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 'I': +#ifdef SMARTCARD + options.smartcard_device = xstrdup(optarg); +#else + fprintf(stderr, "no support for smartcards.\n"); +#endif break; case 't': if (tty_flag) @@ -391,9 +351,8 @@ } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { options.log_level++; break; - } else { + } else fatal("Too high debugging level."); - } /* fallthrough */ case 'V': fprintf(stderr, @@ -410,14 +369,16 @@ break; case 'e': if (optarg[0] == '^' && optarg[2] == 0 && - (u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128) + (u_char) optarg[1] >= 64 && + (u_char) optarg[1] < 128) options.escape_char = (u_char) optarg[1] & 31; else if (strlen(optarg) == 1) options.escape_char = (u_char) optarg[0]; else if (strcmp(optarg, "none") == 0) - options.escape_char = -2; + options.escape_char = SSH_ESCAPECHAR_NONE; else { - fprintf(stderr, "Bad escape character '%s'.\n", optarg); + fprintf(stderr, "Bad escape character '%s'.\n", + optarg); exit(1); } break; @@ -430,23 +391,25 @@ /* SSH1 only */ options.cipher = cipher_number(optarg); if (options.cipher == -1) { - fprintf(stderr, "Unknown cipher type '%s'\n", optarg); + fprintf(stderr, + "Unknown cipher type '%s'\n", + optarg); exit(1); } - if (options.cipher == SSH_CIPHER_3DES) { + if (options.cipher == SSH_CIPHER_3DES) options.ciphers = "3des-cbc"; - } else if (options.cipher == SSH_CIPHER_BLOWFISH) { + else if (options.cipher == SSH_CIPHER_BLOWFISH) options.ciphers = "blowfish-cbc"; - } else { + else options.ciphers = (char *)-1; - } } break; case 'm': if (mac_valid(optarg)) options.macs = xstrdup(optarg); else { - fprintf(stderr, "Unknown mac type '%s'\n", optarg); + fprintf(stderr, "Unknown mac type '%s'\n", + optarg); exit(1); } break; @@ -460,33 +423,38 @@ case 'l': options.user = optarg; break; + + case 'L': case 'R': - if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf, - &fwd_host_port) != 3 && - sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, - &fwd_host_port) != 3) { - fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); + if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]", + sfwd_port, buf, sfwd_host_port) != 3 && + sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]", + sfwd_port, buf, sfwd_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, "%hu/%255[^/]/%hu", &fwd_port, buf, - &fwd_host_port) != 3 && - sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, - &fwd_host_port) != 3) { - fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); - usage(); - /* NOTREACHED */ + if ((fwd_port = a2port(sfwd_port)) == 0 || + (fwd_host_port = a2port(sfwd_host_port)) == 0) { + fprintf(stderr, + "Bad forwarding port(s) '%s'\n", optarg); + exit(1); } - add_local_forward(&options, fwd_port, buf, fwd_host_port); + if (opt == 'L') + add_local_forward(&options, fwd_port, buf, + fwd_host_port); + else if (opt == 'R') + add_remote_forward(&options, fwd_port, buf, + fwd_host_port); break; case 'D': fwd_port = a2port(optarg); if (fwd_port == 0) { - fprintf(stderr, "Bad dynamic port '%s'\n", optarg); + fprintf(stderr, "Bad dynamic port '%s'\n", + optarg); exit(1); } add_local_forward(&options, fwd_port, "socks4", 0); @@ -504,24 +472,53 @@ break; case 'o': dummy = 1; - if (process_config_line(&options, host ? host : "", optarg, - "command-line", 0, &dummy) != 0) + if (process_config_line(&options, host ? host : "", + optarg, "command-line", 0, &dummy) != 0) exit(1); break; case 's': subsystem_flag = 1; break; + case 'b': + options.bind_address = optarg; + break; + case 'F': + config = optarg; + break; default: usage(); } } + ac -= optind; + av += optind; + + if (ac > 0 && !host && **av != '-') { + if (strchr(*av, '@')) { + p = xstrdup(*av); + cp = strchr(p, '@'); + if (cp == NULL || cp == p) + usage(); + options.user = p; + *cp = '\0'; + host = ++cp; + } else + host = *av; + ac--, av++; + if (ac > 0) { + optind = 0; + optreset = 1; + goto again; + } + } + /* Check that we got a host name. */ if (!host) usage(); SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); + channel_set_af(IPv4or6); /* Initialize the command to execute on remote host. */ buffer_init(&command); @@ -531,18 +528,18 @@ * 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) { + if (!ac) { /* No command specified - execute shell on a tty. */ tty_flag = 1; if (subsystem_flag) { - fprintf(stderr, "You must specify a subsystem to invoke.\n"); + fprintf(stderr, + "You must specify a subsystem to invoke.\n"); usage(); } } else { - /* A command has been specified. Store it into the - buffer. */ - for (i = optind; i < ac; i++) { - if (i > optind) + /* A command has been specified. Store it into the buffer. */ + for (i = 0; i < ac; i++) { + if (i) buffer_append(&command, " ", 1); buffer_append(&command, av[i], strlen(av[i])); } @@ -573,12 +570,22 @@ log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, SYSLOG_FACILITY_USER, 1); - /* Read per-user configuration file. */ - snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); - read_config_file(buf, host, &options); + /* + * Read per-user configuration file. Ignore the system wide config + * file if the user specifies a config file on the command line. + */ + if (config != NULL) { + if (!read_config_file(config, host, &options)) + fatal("Can't open user config file %.100s: " + "%.100s", config, strerror(errno)); + } else { + snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, + _PATH_SSH_USER_CONFFILE); + (void)read_config_file(buf, host, &options); - /* Read systemwide configuration file. */ - read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); + /* Read systemwide configuration file after use config. */ + (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); + } /* Fill configuration defaults. */ fill_default_options(&options); @@ -586,6 +593,8 @@ /* reinit */ log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); + seed_rng(); + if (options.user == NULL) options.user = xstrdup(pw->pw_name); @@ -608,58 +617,64 @@ freeaddrinfo(ai); } } + /* Disable rhosts authentication if not running as root. */ +#ifdef HAVE_CYGWIN + /* Ignore uid if running under Windows */ + if (!options.use_privileged_port) { +#else if (original_effective_uid != 0 || !options.use_privileged_port) { +#endif debug("Rhosts Authentication disabled, " "originating port will not be trusted."); options.rhosts_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(pw); - - /* 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. */ - ok = ssh_connect(host, &hostaddr, options.port, + if (ssh_connect(host, &hostaddr, options.port, IPv4or6, options.connection_attempts, - original_effective_uid != 0 || !options.use_privileged_port, - pw, options.proxy_command); +#ifdef HAVE_CYGWIN + options.use_privileged_port, +#else + original_effective_uid == 0 && options.use_privileged_port, +#endif + options.proxy_command) != 0) + exit(1); /* * 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 we cannot access the private keys, load the public keys + * instead and try to execute the ssh-keysign helper instead. */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; - if (ok && (options.rhosts_rsa_authentication || - options.hostbased_authentication)) { + sensitive_data.external_keysign = 0; + if (options.rhosts_rsa_authentication || + options.hostbased_authentication) { sensitive_data.nkeys = 3; sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key)); + + PRIV_START; sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, _PATH_HOST_KEY_FILE, "", NULL); sensitive_data.keys[1] = key_load_private_type(KEY_DSA, _PATH_HOST_DSA_KEY_FILE, "", NULL); sensitive_data.keys[2] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL); + PRIV_END; + + if (sensitive_data.keys[0] == NULL && + sensitive_data.keys[1] == NULL && + sensitive_data.keys[2] == NULL) { + sensitive_data.keys[1] = key_load_public( + _PATH_HOST_DSA_KEY_FILE, NULL); + sensitive_data.keys[2] = key_load_public( + _PATH_HOST_RSA_KEY_FILE, NULL); + sensitive_data.external_keysign = 1; + } } /* * Get rid of any extra privileges that we may have. We will no @@ -668,41 +683,18 @@ * user's home directory if it happens to be on a NFS volume where * root is mapped to nobody. */ - - /* - * Note that some legacy systems need to postpone the following call - * to permanently_set_uid() until the private hostkey is destroyed - * with RSA_free(). Otherwise the calling user could ptrace() the - * process, read the private hostkey and impersonate the host. - * OpenBSD does not allow ptracing of setuid processes. - */ - permanently_set_uid(pw); + seteuid(original_real_uid); + setuid(original_real_uid); /* * Now that we are back to our own permissions, create ~/.ssh * directory if it doesn\'t already exist. */ - snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_DIR); + snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); if (stat(buf, &st) < 0) if (mkdir(buf, 0700) < 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 %hu 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); - } /* load options.identity_files */ load_public_identity_files(); @@ -717,9 +709,10 @@ options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2, original_real_uid); + signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ + /* Log into the remote system. This never returns if the login fails. */ - ssh_login(sensitive_data.keys, sensitive_data.nkeys, - host, (struct sockaddr *)&hostaddr, pw); + ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw); /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { @@ -733,26 +726,53 @@ } xfree(sensitive_data.keys); } + for (i = 0; i < options.num_identity_files; i++) { + if (options.identity_files[i]) { + xfree(options.identity_files[i]); + options.identity_files[i] = NULL; + } + if (options.identity_keys[i]) { + key_free(options.identity_keys[i]); + options.identity_keys[i] = NULL; + } + } exit_status = compat20 ? ssh_session2() : ssh_session(); packet_close(); return exit_status; } -void -x11_get_proto(char *proto, int proto_len, char *data, int data_len) +static void +x11_get_proto(char **_proto, char **_data) { char line[512]; + static char proto[512], data[512]; FILE *f; int got_data = 0, i; + char *display; - if (options.xauth_location) { + *_proto = proto; + *_data = data; + proto[0] = data[0] = '\0'; + if (options.xauth_location && (display = getenv("DISPLAY"))) { /* Try to get Xauthority information for the display. */ - snprintf(line, sizeof line, "%.100s list %.200s 2>" _PATH_DEVNULL, - options.xauth_location, getenv("DISPLAY")); + if (strncmp(display, "localhost:", 10) == 0) + /* + * Handle FamilyLocal case where $DISPLAY does + * not match an authorization entry. For this we + * just try "xauth list unix:displaynum.screennum". + * XXX: "localhost" match to determine FamilyLocal + * is not perfect. + */ + snprintf(line, sizeof line, "%s list unix:%s 2>" + _PATH_DEVNULL, options.xauth_location, display+10); + else + snprintf(line, sizeof line, "%s list %.200s 2>" + _PATH_DEVNULL, options.xauth_location, display); + debug2("x11_get_proto %s", line); f = popen(line, "r"); if (f && fgets(line, sizeof(line), f) && - sscanf(line, "%*s %s %s", proto, data) == 2) + sscanf(line, "%*s %511s %511s", proto, data) == 2) got_data = 1; if (f) pclose(f); @@ -768,17 +788,17 @@ if (!got_data) { u_int32_t rand = 0; - strlcpy(proto, "MIT-MAGIC-COOKIE-1", proto_len); + strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto); for (i = 0; i < 16; i++) { if (i % 4 == 0) rand = arc4random(); - snprintf(data + 2 * i, data_len - 2 * i, "%02x", rand & 0xff); + snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff); rand >>= 8; } } } -void +static void ssh_init_forwarding(void) { int success = 0; @@ -790,7 +810,7 @@ options.local_forwards[i].port, options.local_forwards[i].host, options.local_forwards[i].host_port); - success += channel_request_local_forwarding( + success += channel_setup_local_fwd_listener( options.local_forwards[i].port, options.local_forwards[i].host, options.local_forwards[i].host_port, @@ -812,7 +832,7 @@ } } -void +static void check_agent_present(void) { if (options.forward_agent) { @@ -825,11 +845,10 @@ } } -int +static int ssh_session(void) { int type; - int plen; int interactive = 0; int have_tty = 0; struct winsize ws; @@ -847,7 +866,7 @@ packet_put_int(options.compression_level); packet_send(); packet_write_wait(); - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) packet_start_compression(options.compression_level); else if (type == SSH_SMSG_FAILURE) @@ -867,7 +886,7 @@ cp = getenv("TERM"); if (!cp) cp = ""; - packet_put_string(cp, strlen(cp)); + packet_put_cstring(cp); /* Store window size in the packet. */ if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) @@ -885,7 +904,7 @@ packet_write_wait(); /* Read response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { interactive = 1; have_tty = 1; @@ -896,15 +915,15 @@ } /* Request X11 forwarding if enabled and DISPLAY is set. */ if (options.forward_x11 && getenv("DISPLAY") != NULL) { - char proto[512], data[512]; + char *proto, *data; /* Get reasonable local authentication information. */ - x11_get_proto(proto, sizeof proto, data, sizeof data); + x11_get_proto(&proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); x11_request_forwarding_with_spoofing(0, proto, data); /* Read response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { interactive = 1; } else if (type == SSH_SMSG_FAILURE) { @@ -924,8 +943,8 @@ auth_request_forwarding(); /* Read response from the server. */ - type = packet_read(&plen); - packet_integrity_check(plen, 0, type); + type = packet_read(); + packet_check_eom(); if (type != SSH_SMSG_SUCCESS) log("Warning: Remote host denied authentication agent forwarding."); } @@ -946,7 +965,7 @@ int len = buffer_len(&command); if (len > 900) len = 900; - debug("Sending command: %.*s", len, buffer_ptr(&command)); + debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); packet_start(SSH_CMSG_EXEC_CMD); packet_put_string(buffer_ptr(&command), buffer_len(&command)); packet_send(); @@ -959,11 +978,12 @@ } /* Enter the interactive session. */ - return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); + return client_loop(have_tty, tty_flag ? + options.escape_char : SSH_ESCAPECHAR_NONE, 0); } -void -client_subsystem_reply(int type, int plen, void *ctxt) +static void +client_subsystem_reply(int type, u_int32_t seq, void *ctxt) { int id, len; @@ -971,20 +991,42 @@ len = buffer_len(&command); if (len > 900) len = 900; - packet_done(); + packet_check_eom(); if (type == SSH2_MSG_CHANNEL_FAILURE) fatal("Request for subsystem '%.*s' failed on channel %d", - len, buffer_ptr(&command), id); + len, (u_char *)buffer_ptr(&command), id); } void -ssh_session2_callback(int id, void *arg) +client_global_request_reply(int type, u_int32_t seq, void *ctxt) +{ + int i; + + i = client_global_request_id++; + if (i >= options.num_remote_forwards) { + debug("client_global_request_reply: too many replies %d > %d", + i, options.num_remote_forwards); + return; + } + debug("remote forward %s for: listen %d, connect %s:%d", + type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", + options.remote_forwards[i].port, + options.remote_forwards[i].host, + options.remote_forwards[i].host_port); + if (type == SSH2_MSG_REQUEST_FAILURE) + log("Warning: remote port forwarding failed for listen port %d", + options.remote_forwards[i].port); +} + +/* request pty/x11/agent/tcpfwd/shell for channel */ +static void +ssh_session2_setup(int id, void *arg) { int len; int interactive = 0; struct termios tio; - debug("client_init id %d arg %ld", id, (long)arg); + debug("ssh_session2_setup: id %d", id); if (tty_flag) { struct winsize ws; @@ -1010,9 +1052,9 @@ } if (options.forward_x11 && getenv("DISPLAY") != NULL) { - char proto[512], data[512]; + char *proto, *data; /* Get reasonable local authentication information. */ - x11_get_proto(proto, sizeof proto, data, sizeof data); + x11_get_proto(&proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); x11_request_forwarding_with_spoofing(id, proto, data); @@ -1032,32 +1074,32 @@ if (len > 900) len = 900; if (subsystem_flag) { - debug("Sending subsystem: %.*s", len, buffer_ptr(&command)); + debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command)); channel_request_start(id, "subsystem", /*want reply*/ 1); /* register callback for reply */ - /* XXX we asume that client_loop has already been called */ + /* XXX we assume that client_loop has already been called */ dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply); dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply); } else { - debug("Sending command: %.*s", len, buffer_ptr(&command)); + debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command)); channel_request_start(id, "exec", 0); } packet_put_string(buffer_ptr(&command), buffer_len(&command)); packet_send(); } else { - channel_request(id, "shell", 0); + channel_request_start(id, "shell", 0); + packet_send(); } - /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */ - /* register different callback, etc. XXX */ packet_set_interactive(interactive); } -int -ssh_session2_command(void) +/* open new channel for a session */ +static int +ssh_session2_open(void) { - int id, window, packetmax; - int in, out, err; + Channel *c; + int window, packetmax, in, out, err; if (stdin_null_flag) { in = open(_PATH_DEVNULL, O_RDONLY); @@ -1080,50 +1122,74 @@ window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; - if (!tty_flag) { - window *= 2; - packetmax *=2; + if (tty_flag) { + window >>= 1; + packetmax >>= 1; } - id = channel_new( + c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"), /*nonblock*/0); -debug("channel_new: %d", id); + debug3("ssh_session2_open: channel_new: %d", c->self); - channel_open(id); - channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, - ssh_session2_callback, (void *)0); + channel_send_open(c->self); + if (!no_shell_flag) + channel_register_confirm(c->self, ssh_session2_setup); - return id; + return c->self; } -int +static int ssh_session2(void) { - int id; + int id = -1; /* XXX should be pre-session */ ssh_init_forwarding(); - id = no_shell_flag ? -1 : ssh_session2_command(); + if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) + id = ssh_session2_open(); /* If requested, let ssh continue in the background. */ if (fork_after_authentication_flag) if (daemon(1, 1) < 0) fatal("daemon() failed: %.200s", strerror(errno)); - return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); + return client_loop(tty_flag, tty_flag ? + options.escape_char : SSH_ESCAPECHAR_NONE, id); } -void +static void load_public_identity_files(void) { char *filename; + int i = 0; Key *public; - int i; +#ifdef SMARTCARD + Key **keys; - for (i = 0; i < options.num_identity_files; i++) { + if (options.smartcard_device != NULL && + options.num_identity_files < SSH_MAX_IDENTITY_FILES && + (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) { + int count = 0; + for (i = 0; keys[i] != NULL; i++) { + count++; + memmove(&options.identity_files[1], &options.identity_files[0], + sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); + memmove(&options.identity_keys[1], &options.identity_keys[0], + sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); + options.num_identity_files++; + options.identity_keys[0] = keys[i]; + options.identity_files[0] = xstrdup("smartcard key");; + } + if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) + options.num_identity_files = SSH_MAX_IDENTITY_FILES; + i = count; + xfree(keys); + } +#endif /* SMARTCARD */ + for (; i < options.num_identity_files; i++) { filename = tilde_expand_filename(options.identity_files[i], original_real_uid); public = key_load_public(filename, NULL); Index: src/crypto/openssh/ssh.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh.h,v retrieving revision 1.6.2.6 diff -u -u -r1.6.2.6 ssh.h --- src/crypto/openssh/ssh.h 28 Sep 2001 01:33:35 -0000 1.6.2.6 +++ src/crypto/openssh/ssh.h 30 Jun 2002 11:38:01 -0000 @@ -1,3 +1,6 @@ +/* $OpenBSD: ssh.h,v 1.71 2002/06/22 02:00:29 stevesk Exp $ */ +/* $FreeBSD: src/crypto/openssh/ssh.h,v 1.21 2002/06/29 11:48:59 des Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,12 +13,19 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: ssh.h,v 1.62 2001/01/23 10:45:10 markus Exp $"); */ -/* RCSID("$FreeBSD: src/crypto/openssh/ssh.h,v 1.6.2.6 2001/09/28 01:33:35 green Exp $"); */ - #ifndef SSH_H #define SSH_H +#include /* For struct sockaddr_in */ +#include /* For struct pw */ +#include /* For va_list */ +#include /* For LOG_AUTH and friends */ +#include /* For struct sockaddr_storage */ +#include "openbsd-compat/fake-socket.h" /* For struct sockaddr_storage */ +#ifdef HAVE_SYS_SELECT_H +# include +#endif + /* Cipher used for encrypting authentication files. */ #define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES @@ -32,7 +42,7 @@ #define SSH_MAX_IDENTITY_FILES 100 /* - * Major protocol version. Different version indicates major incompatiblity + * Major protocol version. Different version indicates major incompatibility * that prevents communication. * * Minor protocol version. Different version indicates minor incompatibility @@ -51,9 +61,13 @@ */ #define SSH_SERVICE_NAME "ssh" +#if defined(USE_PAM) && !defined(SSHD_PAM_SERVICE) +# define SSHD_PAM_SERVICE __progname +#endif + /* - * Name of the environment variable containing the pathname of the - * authentication socket. + * Name of the environment variable containing the process ID of the + * authentication agent. */ #define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID" @@ -83,11 +97,19 @@ /* Name of Kerberos service for SSH to use. */ #define KRB4_SERVICE_NAME "rcmd" -/* Kerberos IV tickets can't be forwarded. This is an AFS hack! */ -#define SSH_CMSG_HAVE_KRB4_TGT SSH_CMSG_HAVE_KERBEROS_TGT /* credentials (s) */ +/* Used to identify ``EscapeChar none'' */ +#define SSH_ESCAPECHAR_NONE -2 + +/* + * unprivileged user when UsePrivilegeSeparation=yes; + * sshd will change its privileges to this user and its + * primary group. + */ +#ifndef SSH_PRIVSEP_USER +#define SSH_PRIVSEP_USER "sshd" +#endif -#ifdef USE_PAM -#include "auth-pam.h" -#endif /* USE_PAM */ +/* Minimum modulus size (n) for RSA keys. */ +#define SSH_RSA_MINIMUM_MODULUS_SIZE 768 #endif /* SSH_H */ Index: src/crypto/openssh/ssh1.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh1.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 ssh1.h --- src/crypto/openssh/ssh1.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/ssh1.h 30 Jun 2002 11:38:01 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh1.h,v 1.2 2001/01/29 01:58:18 niklas Exp $ */ +/* $OpenBSD: ssh1.h,v 1.3 2001/05/30 12:55:13 markus Exp $ */ /* * Author: Tatu Ylonen @@ -66,6 +66,10 @@ #define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */ #define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */ +/* protocol version 1.5 overloads some version 1.3 message types */ +#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE +#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION + /* * Authentication methods. New types can be added, but old types should not * be removed for compatibility. The maximum allowed value is 31. @@ -83,4 +87,3 @@ /* 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 */ - Index: src/crypto/openssh/ssh2.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh2.h,v retrieving revision 1.1.1.2.2.4 diff -u -u -r1.1.1.2.2.4 ssh2.h --- src/crypto/openssh/ssh2.h 28 Sep 2001 01:33:35 -0000 1.1.1.2.2.4 +++ src/crypto/openssh/ssh2.h 30 Jun 2002 11:38:01 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: ssh2.h,v 1.8 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -52,7 +54,21 @@ * * 192-255 Local extensions */ -/* RCSID("$OpenBSD: ssh2.h,v 1.6 2001/03/27 17:46:49 provos Exp $"); */ + +/* ranges */ + +#define SSH2_MSG_TRANSPORT_MIN 1 +#define SSH2_MSG_TRANSPORT_MAX 49 +#define SSH2_MSG_USERAUTH_MIN 50 +#define SSH2_MSG_USERAUTH_MAX 79 +#define SSH2_MSG_CONNECTION_MIN 80 +#define SSH2_MSG_CONNECTION_MAX 127 +#define SSH2_MSG_RESERVED_MIN 128 +#define SSH2_MSG_RESERVED_MAX 191 +#define SSH2_MSG_LOCAL_MIN 192 +#define SSH2_MSG_LOCAL_MAX 255 +#define SSH2_MSG_MIN 1 +#define SSH2_MSG_MAX 255 /* transport layer: generic */ Index: src/crypto/openssh/ssh_config =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ssh_config,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 ssh_config --- src/crypto/openssh/ssh_config 28 Sep 2001 01:33:35 -0000 1.2.2.4 +++ src/crypto/openssh/ssh_config 30 Jun 2002 11:38:01 -0000 @@ -1,13 +1,10 @@ -# 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. -# -# $OpenBSD: ssh_config,v 1.10 2001/04/03 21:19:38 todd Exp $ -# $FreeBSD: src/crypto/openssh/ssh_config,v 1.2.2.4 2001/09/28 01:33:35 green Exp $ +# $OpenBSD: ssh_config,v 1.15 2002/06/20 20:03:34 stevesk Exp $ +# $FreeBSD: src/crypto/openssh/ssh_config,v 1.16 2002/06/30 10:32:09 des Exp $ -# This is ssh client systemwide configuration file. See ssh(1) for more -# information. This file provides defaults for users, and the values can -# be changed in per-user configuration files or on the command line. +# This is the ssh client system-wide configuration file. See +# ssh_config(5) for more information. 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 @@ -19,22 +16,22 @@ # Site-wide defaults for various options -Host * +# Host * # ForwardAgent no # ForwardX11 no # RhostsAuthentication no -# RhostsRSAAuthentication yes +# RhostsRSAAuthentication no # RSAAuthentication yes # PasswordAuthentication yes -# FallBackToRsh no -# UseRsh no # BatchMode no # CheckHostIP yes -# StrictHostKeyChecking yes +# StrictHostKeyChecking ask # IdentityFile ~/.ssh/identity -# IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_rsa +# IdentityFile ~/.ssh/id_dsa # Port 22 - Protocol 1,2 -# Cipher blowfish +# Protocol 2,1 +# Cipher 3des +# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc # EscapeChar ~ +# VersionAddendum FreeBSD-20020629 Index: src/crypto/openssh/ssh_config.5 =================================================================== RCS file: src/crypto/openssh/ssh_config.5 diff -N src/crypto/openssh/ssh_config.5 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ssh_config.5 30 Jun 2002 11:38:01 -0000 @@ -0,0 +1,625 @@ +.\" -*- nroff -*- +.\" +.\" Author: Tatu Ylonen +.\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland +.\" All rights reserved +.\" +.\" 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". +.\" +.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. +.\" Copyright (c) 1999 Aaron Campbell. All rights reserved. +.\" Copyright (c) 1999 Theo de Raadt. 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $OpenBSD: ssh_config.5,v 1.1 2002/06/20 19:56:07 stevesk Exp $ +.\" $FreeBSD: src/crypto/openssh/ssh_config.5,v 1.4 2002/06/29 10:53:57 des Exp $ +.Dd September 25, 1999 +.Dt SSH_CONFIG 5 +.Os +.Sh NAME +.Nm ssh_config +.Nd OpenSSH SSH client configuration files +.Sh SYNOPSIS +.Bl -tag -width Ds -compact +.It Pa $HOME/.ssh/config +.It Pa /etc/ssh/ssh_config +.El +.Sh DESCRIPTION +.Nm ssh +obtains configuration data from the following sources in +the following order: +command line options, user's configuration file +.Pq Pa $HOME/.ssh/config , +and system-wide configuration file +.Pq Pa /etc/ssh/ssh_config . +.Pp +For each parameter, the first obtained value +will be used. +The configuration files contain sections bracketed by +.Dq 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. +.Pp +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. +.Pp +The configuration file has the following format: +.Pp +Empty lines and lines starting with +.Ql # +are comments. +.Pp +Otherwise a line is of the format +.Dq keyword arguments . +Configuration options may be separated by whitespace or +optional whitespace and exactly one +.Ql = ; +the latter format is useful to avoid the need to quote whitespace +when specifying configuration options using the +.Nm ssh , +.Nm scp +and +.Nm sftp +.Fl o +option. +.Pp +The possible +keywords and their meanings are as follows (note that +keywords are case-insensitive and arguments are case-sensitive): +.Bl -tag -width Ds +.It Cm Host +Restricts the following declarations (up to the next +.Cm Host +keyword) to be only for those hosts that match one of the patterns +given after the keyword. +.Ql \&* +and +.Ql ? +can be used as wildcards in the +patterns. +A single +.Ql \&* +as a pattern can be used to provide global +defaults for all hosts. +The host is the +.Ar hostname +argument given on the command line (i.e., the name is not converted to +a canonicalized host name before matching). +.It Cm AFSTokenPassing +Specifies whether to pass AFS tokens to remote host. +The argument to this keyword must be +.Dq yes +or +.Dq no . +This option applies to protocol version 1 only. +.It Cm BatchMode +If set to +.Dq yes , +passphrase/password querying will be disabled. +This option is useful in scripts and other batch jobs where no user +is present to supply the password. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm BindAddress +Specify the interface to transmit from on machines with multiple +interfaces or aliased addresses. +Note that this option does not work if +.Cm UsePrivilegedPort +is set to +.Dq yes . +.It Cm ChallengeResponseAuthentication +Specifies whether to use challenge response authentication. +The argument to this keyword must be +.Dq yes +or +.Dq no . +The default is +.Dq yes . +.It Cm CheckHostIP +If this flag is set to +.Dq yes , +ssh will additionally check the host IP address in the +.Pa known_hosts +file. +This allows ssh to detect if a host key changed due to DNS spoofing. +If the option is set to +.Dq no , +the check will not be executed. +The default is +.Dq yes . +.It Cm Cipher +Specifies the cipher to use for encrypting the session +in protocol version 1. +Currently, +.Dq blowfish , +.Dq 3des , +and +.Dq des +are supported. +.Ar des +is only supported in the +.Nm ssh +client for interoperability with legacy protocol 1 implementations +that do not support the +.Ar 3des +cipher. Its use is strongly discouraged due to cryptographic +weaknesses. +The default is +.Dq 3des . +.It Cm Ciphers +Specifies the ciphers allowed for protocol version 2 +in order of preference. +Multiple ciphers must be comma-separated. +The default is +.Pp +.Bd -literal + ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, + aes192-cbc,aes256-cbc'' +.Ed +.It Cm ClearAllForwardings +Specifies that all local, remote and dynamic port forwardings +specified in the configuration files or on the command line be +cleared. This option is primarily useful when used from the +.Nm ssh +command line to clear port forwardings set in +configuration files, and is automatically set by +.Xr scp 1 +and +.Xr sftp 1 . +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm Compression +Specifies whether to use compression. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm CompressionLevel +Specifies the compression level to use if compression is enabled. +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 +.Xr gzip 1 . +Note that this option applies to protocol version 1 only. +.It Cm ConnectionAttempts +Specifies the number of tries (one per second) to make before exiting. +The argument must be an integer. +This may be useful in scripts if the connection sometimes fails. +The default is 1. +.It Cm DynamicForward +Specifies that a TCP/IP port on the local machine be forwarded +over the secure channel, and the application +protocol is then used to determine where to connect to from the +remote machine. The argument must be a port number. +Currently the SOCKS4 protocol is supported, and +.Nm ssh +will act as a SOCKS4 server. +Multiple forwardings may be specified, and +additional forwardings can be given on the command line. Only +the superuser can forward privileged ports. +.It Cm EscapeChar +Sets the escape character (default: +.Ql ~ ) . +The escape character can also +be set on the command line. +The argument should be a single character, +.Ql ^ +followed by a letter, or +.Dq none +to disable the escape +character entirely (making the connection transparent for binary +data). +.It Cm ForwardAgent +Specifies whether the connection to the authentication agent (if any) +will be forwarded to the remote machine. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm ForwardX11 +Specifies whether X11 connections will be automatically redirected +over the secure channel and +.Ev DISPLAY +set. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm GatewayPorts +Specifies whether remote hosts are allowed to connect to local +forwarded ports. +By default, +.Nm ssh +binds local port forwardings to the loopback address. This +prevents other remote hosts from connecting to forwarded ports. +.Cm GatewayPorts +can be used to specify that +.Nm ssh +should bind local port forwardings to the wildcard address, +thus allowing remote hosts to connect to forwarded ports. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm GlobalKnownHostsFile +Specifies a file to use for the global +host key database instead of +.Pa /etc/ssh/ssh_known_hosts . +.It Cm HostbasedAuthentication +Specifies whether to try rhosts based authentication with public key +authentication. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +This option applies to protocol version 2 only and +is similar to +.Cm RhostsRSAAuthentication . +.It Cm HostKeyAlgorithms +Specifies the protocol version 2 host key algorithms +that the client wants to use in order of preference. +The default for this option is: +.Dq ssh-rsa,ssh-dss . +.It Cm HostKeyAlias +Specifies an alias that should be used instead of the +real host name when looking up or saving the host key +in the host key database files. +This option is useful for tunneling ssh connections +or for multiple servers running on a single host. +.It Cm HostName +Specifies the real host name to log into. +This can be used to specify nicknames 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 +.Cm HostName +specifications). +.It Cm IdentityFile +Specifies a file from which the user's RSA or DSA authentication identity +is read. The default is +.Pa $HOME/.ssh/identity +for protocol version 1, and +.Pa $HOME/.ssh/id_rsa +and +.Pa $HOME/.ssh/id_dsa +for protocol version 2. +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. +.It Cm KeepAlive +Specifies whether the system should send TCP 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. +.Pp +The default is +.Dq 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. +.Pp +To disable keepalives, the value should be set to +.Dq no . +.It Cm KerberosAuthentication +Specifies whether Kerberos authentication will be used. +The argument to this keyword must be +.Dq yes +or +.Dq no . +.It Cm KerberosTgtPassing +Specifies whether a Kerberos TGT will be forwarded to the server. +This will only work if the Kerberos server is actually an AFS kaserver. +The argument to this keyword must be +.Dq yes +or +.Dq no . +.It Cm LocalForward +Specifies that a TCP/IP port on the local machine be forwarded over +the secure channel to the specified host and port from the remote machine. +The first argument must be a port number, and the second must be +.Ar host:port . +IPv6 addresses can be specified with an alternative syntax: +.Ar host/port . +Multiple forwardings may be specified, and additional +forwardings can be given on the command line. +Only the superuser can forward privileged ports. +.It Cm LogLevel +Gives the verbosity level that is used when logging messages from +.Nm ssh . +The possible values are: +QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3. +The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 +and DEBUG3 each specify higher levels of verbose output. +.It Cm MACs +Specifies the MAC (message authentication code) algorithms +in order of preference. +The MAC algorithm is used in protocol version 2 +for data integrity protection. +Multiple algorithms must be comma-separated. +The default is +.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 . +.It Cm NoHostAuthenticationForLocalhost +This option can be used if the home directory is shared across machines. +In this case localhost will refer to a different machine on each of +the machines and the user will get many warnings about changed host keys. +However, this option disables host authentication for localhost. +The argument to this keyword must be +.Dq yes +or +.Dq no . +The default is to check the host key for localhost. +.It Cm NumberOfPasswordPrompts +Specifies the number of password prompts before giving up. +The argument to this keyword must be an integer. +Default is 3. +.It Cm PasswordAuthentication +Specifies whether to use password authentication. +The argument to this keyword must be +.Dq yes +or +.Dq no . +The default is +.Dq yes . +.It Cm Port +Specifies the port number to connect on the remote host. +Default is 22. +.It Cm PreferredAuthentications +Specifies the order in which the client should try protocol 2 +authentication methods. This allows a client to prefer one method (e.g. +.Cm keyboard-interactive ) +over another method (e.g. +.Cm password ) +The default for this option is: +.Dq hostbased,publickey,keyboard-interactive,password . +.It Cm Protocol +Specifies the protocol versions +.Nm ssh +should support in order of preference. +The possible values are +.Dq 1 +and +.Dq 2 . +Multiple versions must be comma-separated. +The default is +.Dq 2,1 . +This means that +.Nm ssh +tries version 2 and falls back to version 1 +if version 2 is not available. +.It Cm 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 +.Pa /bin/sh . +In the command string, +.Ql %h +will be substituted by the host name to +connect and +.Ql %p +by the port. +The command can be basically anything, +and should read from its standard input and write to its standard output. +It should eventually connect an +.Xr sshd 8 +server running on some machine, or execute +.Ic 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 +.Cm CheckHostIP +is not available for connects with a proxy command. +.Pp +.It Cm PubkeyAuthentication +Specifies whether to try public key authentication. +The argument to this keyword must be +.Dq yes +or +.Dq no . +The default is +.Dq yes . +This option applies to protocol version 2 only. +.It Cm RemoteForward +Specifies that a TCP/IP port on the remote machine be forwarded over +the secure channel to the specified host and port from the local machine. +The first argument must be a port number, and the second must be +.Ar host:port . +IPv6 addresses can be specified with an alternative syntax: +.Ar host/port . +Multiple forwardings may be specified, and additional +forwardings can be given on the command line. +Only the superuser can forward privileged ports. +.It Cm RhostsAuthentication +Specifies whether to try rhosts based authentication. +Note that this +declaration only affects the client side and has no effect whatsoever +on security. +Most servers do not permit RhostsAuthentication because it +is not secure (see +.Cm RhostsRSAAuthentication ) . +The argument to this keyword must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +This option applies to protocol version 1 only. +.It Cm RhostsRSAAuthentication +Specifies whether to try rhosts based authentication with RSA host +authentication. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +This option applies to protocol version 1 only and requires +.Nm ssh +to be setuid root. +.It Cm RSAAuthentication +Specifies whether to try RSA authentication. +The argument to this keyword must be +.Dq yes +or +.Dq no . +RSA authentication will only be +attempted if the identity file exists, or an authentication agent is +running. +The default is +.Dq yes . +Note that this option applies to protocol version 1 only. +.It Cm SmartcardDevice +Specifies which smartcard device to use. The argument to this keyword is +the device +.Nm ssh +should use to communicate with a smartcard used for storing the user's +private RSA key. By default, no device is specified and smartcard support +is not activated. +.It Cm StrictHostKeyChecking +If this flag is set to +.Dq yes , +.Nm ssh +will never automatically add host keys to the +.Pa $HOME/.ssh/known_hosts +file, and refuses to connect to hosts whose host key has changed. +This provides maximum protection against trojan horse attacks, +however, can be annoying when the +.Pa /etc/ssh/ssh_known_hosts +file is poorly maintained, or connections to new hosts are +frequently made. +This option forces the user to manually +add all new hosts. +If this flag is set to +.Dq no , +.Nm ssh +will automatically add new host keys to the +user known hosts files. +If this flag is set to +.Dq ask , +new host keys +will be added to the user known host files only after the user +has confirmed that is what they really want to do, and +.Nm ssh +will refuse to connect to hosts whose host key has changed. +The host keys of +known hosts will be verified automatically in all cases. +The argument must be +.Dq yes , +.Dq no +or +.Dq ask . +The default is +.Dq ask . +.It Cm UsePrivilegedPort +Specifies whether to use a privileged port for outgoing connections. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +Note that this option must be set to +.Dq yes +if +.Cm RhostsAuthentication +and +.Cm RhostsRSAAuthentication +authentications are needed with older servers. +.It Cm User +Specifies the user to log in as. +This can be useful when a different user name is used on different machines. +This saves the trouble of +having to remember to give the user name on the command line. +.It Cm UserKnownHostsFile +Specifies a file to use for the user +host key database instead of +.Pa $HOME/.ssh/known_hosts . +.It Cm VersionAddendum +Specifies a string to append to the regular version string to identify +OS- or site-specific modifications. +.It Cm XAuthLocation +Specifies the location of the +.Xr xauth 1 +program. +The default is +.Pa /usr/X11R6/bin/xauth . +.El +.Sh FILES +.Bl -tag -width Ds +.It Pa $HOME/.ssh/config +This is the per-user configuration file. +The format of this file is described above. +This file is used by the +.Nm 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. +.It Pa /etc/ssh/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. +.El +.Sh AUTHORS +OpenSSH is a derivative of the original and free +ssh 1.2.12 release by Tatu Ylonen. +Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, +Theo de Raadt and Dug Song +removed many bugs, re-added newer features and +created OpenSSH. +Markus Friedl contributed the support for SSH +protocol versions 1.5 and 2.0. +.Sh SEE ALSO +.Xr ssh 1 Index: src/crypto/openssh/ssh_prng_cmds.in =================================================================== RCS file: src/crypto/openssh/ssh_prng_cmds.in diff -N src/crypto/openssh/ssh_prng_cmds.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/ssh_prng_cmds.in 30 Jun 2002 11:38:01 -0000 @@ -0,0 +1,75 @@ +# entropy gathering commands + +# Format is: "program-name args" path rate + +# The "rate" represents the number of bits of usuable entropy per +# byte of command output. Be conservative. +# +# $Id$ + +"ls -alni /var/log" @PROG_LS@ 0.02 +"ls -alni /var/adm" @PROG_LS@ 0.02 +"ls -alni /usr/adm" @PROG_LS@ 0.02 +"ls -alni /var/mail" @PROG_LS@ 0.02 +"ls -alni /usr/mail" @PROG_LS@ 0.02 +"ls -alni /var/adm/syslog" @PROG_LS@ 0.02 +"ls -alni /usr/adm/syslog" @PROG_LS@ 0.02 +"ls -alni /var/spool/mail" @PROG_LS@ 0.02 +"ls -alni /proc" @PROG_LS@ 0.02 +"ls -alni /tmp" @PROG_LS@ 0.02 +"ls -alni /var/tmp" @PROG_LS@ 0.02 +"ls -alni /usr/tmp" @PROG_LS@ 0.02 +"ls -alTi /var/log" @PROG_LS@ 0.02 +"ls -alTi /var/adm" @PROG_LS@ 0.02 +"ls -alTi /var/mail" @PROG_LS@ 0.02 +"ls -alTi /var/adm/syslog" @PROG_LS@ 0.02 +"ls -alTi /var/spool/mail" @PROG_LS@ 0.02 +"ls -alTi /proc" @PROG_LS@ 0.02 +"ls -alTi /tmp" @PROG_LS@ 0.02 +"ls -alTi /var/tmp" @PROG_LS@ 0.02 +"ls -alTi /usr/tmp" @PROG_LS@ 0.02 + +"netstat -an" @PROG_NETSTAT@ 0.05 +"netstat -in" @PROG_NETSTAT@ 0.05 +"netstat -rn" @PROG_NETSTAT@ 0.02 +"netstat -pn" @PROG_NETSTAT@ 0.02 +"netstat -ia" @PROG_NETSTAT@ 0.05 +"netstat -s" @PROG_NETSTAT@ 0.02 +"netstat -is" @PROG_NETSTAT@ 0.07 + +"arp -a -n" @PROG_ARP@ 0.02 + +"ifconfig -a" @PROG_IFCONFIG@ 0.02 + +"ps laxww" @PROG_PS@ 0.03 +"ps -al" @PROG_PS@ 0.03 +"ps -efl" @PROG_PS@ 0.03 +"jstat" @PROG_JSTAT@ 0.07 + +"w" @PROG_W@ 0.05 + +"who -i" @PROG_WHO@ 0.01 + +"last" @PROG_LAST@ 0.01 + +"lastlog" @PROG_LASTLOG@ 0.01 + +"df" @PROG_DF@ 0.01 +"df -i" @PROG_DF@ 0.01 + +"sar -d" @PROG_SAR@ 0.04 + +"vmstat" @PROG_VMSTAT@ 0.01 +"uptime" @PROG_UPTIME@ 0.01 + +"ipcs -a" @PROG_IPCS@ 0.01 + +"tail -200 /var/log/messages" @PROG_TAIL@ 0.01 +"tail -200 /var/log/syslog" @PROG_TAIL@ 0.01 +"tail -200 /var/adm/messages" @PROG_TAIL@ 0.01 +"tail -200 /var/adm/syslog" @PROG_TAIL@ 0.01 +"tail -200 /var/adm/syslog/syslog.log" @PROG_TAIL@ 0.01 +"tail -200 /var/log/maillog" @PROG_TAIL@ 0.01 +"tail -200 /var/adm/maillog" @PROG_TAIL@ 0.01 +"tail -200 /var/adm/syslog/mail.log" @PROG_TAIL@ 0.01 + Index: src/crypto/openssh/sshconnect.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshconnect.c,v retrieving revision 1.4.2.8 diff -u -u -r1.4.2.8 sshconnect.c --- src/crypto/openssh/sshconnect.c 28 Sep 2001 01:33:35 -0000 1.4.2.8 +++ src/crypto/openssh/sshconnect.c 30 Jun 2002 11:38:01 -0000 @@ -13,8 +13,8 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.104 2001/04/12 19:15:25 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/sshconnect.c,v 1.4.2.8 2001/09/28 01:33:35 green Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.126 2002/06/23 03:30:17 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/sshconnect.c,v 1.22 2002/06/29 11:48:59 des Exp $"); #include @@ -32,25 +32,37 @@ #include "readconf.h" #include "atomicio.h" #include "misc.h" -#include "auth.h" -#include "ssh1.h" -#include "canohost.h" +#include "readpass.h" char *client_version_string = NULL; char *server_version_string = NULL; +/* import */ extern Options options; extern char *__progname; +extern uid_t original_real_uid; +extern uid_t original_effective_uid; -/* AF_UNSPEC or AF_INET or AF_INET6 */ -extern int IPv4or6; +#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ +#define INET6_ADDRSTRLEN 46 +#endif + +static const char * +sockaddr_ntop(struct sockaddr *sa, socklen_t salen) +{ + static char addrbuf[NI_MAXHOST]; + + if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0, + NI_NUMERICHOST) != 0) + fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed"); + return addrbuf; +} /* * Connect to the given ssh server using a proxy command. */ -int -ssh_proxy_connect(const char *host, u_short port, struct passwd *pw, - const char *proxy_command) +static int +ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) { Buffer command; const char *cp; @@ -91,7 +103,7 @@ /* 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)); + strerror(errno)); debug("Executing proxy command: %.500s", command_string); @@ -100,7 +112,8 @@ char *argv[10]; /* Child. Permanently give up superuser privileges. */ - permanently_set_uid(pw); + seteuid(original_real_uid); + setuid(original_real_uid); /* Redirect stdin and stdout. */ close(pin[1]); @@ -142,16 +155,18 @@ /* Set the connection file descriptors. */ packet_set_connection(pout[0], pin[1]); - return 1; + /* Indicate OK return */ + return 0; } /* * Creates a (possibly privileged) socket for use as the ssh connection. */ -int -ssh_create_socket(struct passwd *pw, int privileged, int family) +static int +ssh_create_socket(int privileged, int family) { - int sock; + int sock, gaierr; + struct addrinfo hints, *res; /* * If we are running as root and want to connect to a privileged @@ -159,41 +174,65 @@ */ if (privileged) { int p = IPPORT_RESERVED - 1; + PRIV_START; sock = rresvport_af(&p, family); + PRIV_END; if (sock < 0) error("rresvport: af=%d %.100s", family, strerror(errno)); else 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(pw); - sock = socket(family, SOCK_STREAM, 0); - if (sock < 0) - error("socket: %.100s", strerror(errno)); - restore_uid(); + return sock; + } + sock = socket(family, SOCK_STREAM, 0); + if (sock < 0) + error("socket: %.100s", strerror(errno)); + + /* Bind the socket to an alternative local IP address */ + if (options.bind_address == NULL) + return sock; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + gaierr = getaddrinfo(options.bind_address, "0", &hints, &res); + if (gaierr) { + error("getaddrinfo: %s: %s", options.bind_address, + gai_strerror(gaierr)); + close(sock); + return -1; } + if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { + error("bind: %s: %s", options.bind_address, strerror(errno)); + close(sock); + freeaddrinfo(res); + return -1; + } + freeaddrinfo(res); return sock; } /* * Opens a TCP/IP connection to the remote server on the given host. * The address of the remote host will be returned in hostaddr. - * If port is 0, the default port will be used. If anonymous is zero, + * If port is 0, the default port will be used. If needpriv is true, * a privileged port will be allocated to make the connection. - * This requires super-user privileges if anonymous is false. + * This requires super-user privileges if needpriv is true. * 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. + * Return values: + * 0 for OK + * ECONNREFUSED if we got a "Connection Refused" by the peer on any address + * ECONNABORTED if we failed without a "Connection refused" + * Suitable error messages for the connection failure will already have been + * printed. */ int ssh_connect(const char *host, struct sockaddr_storage * hostaddr, - u_short port, int connection_attempts, - int anonymous, struct passwd *pw, - const char *proxy_command) + u_short port, int family, int connection_attempts, + int needpriv, const char *proxy_command) { int gaierr; int on = 1; @@ -202,9 +241,14 @@ struct addrinfo hints, *ai, *aitop; struct linger linger; struct servent *sp; + /* + * Did we get only other errors than "Connection refused" (which + * should block fallback to rsh and similar), or did we get at least + * one "Connection refused"? + */ + int full_failure = 1; - debug("ssh_connect: getuid %u geteuid %u anon %d", - (u_int) getuid(), (u_int) geteuid(), anonymous); + debug("ssh_connect: needpriv %d", needpriv); /* Get default port if port has not been set. */ if (port == 0) { @@ -216,14 +260,14 @@ } /* If a proxy command is given, connect using it. */ if (proxy_command != NULL) - return ssh_proxy_connect(host, port, pw, proxy_command); + return ssh_proxy_connect(host, port, proxy_command); /* No proxy command. */ memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; + hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", port); + snprintf(strport, sizeof strport, "%u", port); if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) fatal("%s: %.100s: %s", __progname, host, gai_strerror(gaierr)); @@ -232,8 +276,8 @@ * 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++) { + */ + for (attempt = 0; ;) { if (attempt > 0) debug("Trying again..."); @@ -252,38 +296,36 @@ host, ntop, strport); /* Create a socket for connecting. */ - sock = ssh_create_socket(pw, - !anonymous && geteuid() == 0, - ai->ai_family); + sock = ssh_create_socket(needpriv, ai->ai_family); if (sock < 0) + /* Any error is already output */ continue; - /* 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(pw); if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { /* Successful connection. */ memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); - restore_uid(); break; } else { - debug("connect: %.100s", strerror(errno)); - restore_uid(); + if (errno == ECONNREFUSED) + full_failure = 0; + log("ssh: connect to address %s port %s: %s", + sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), + strport, strerror(errno)); /* * Close the failed socket; there appear to * be some problems when reusing a socket for * which connect() has already returned an * error. */ - shutdown(sock, SHUT_RDWR); close(sock); } } if (ai) break; /* Successful connection. */ + attempt++; + if (attempt >= connection_attempts) + break; /* Sleep a moment before retrying. */ sleep(1); } @@ -292,7 +334,7 @@ /* Return failure if we didn't get a successful connection. */ if (attempt >= connection_attempts) - return 0; + return full_failure ? ECONNABORTED : ECONNREFUSED; debug("Connection established."); @@ -314,14 +356,14 @@ /* Set the connection. */ packet_set_connection(sock, sock); - return 1; + return 0; } /* * Waits for the server identification string, and sends our own * identification string. */ -void +static void ssh_exchange_identification(void) { char buf[256], remote_version[256]; /* must be same size! */ @@ -363,12 +405,12 @@ &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); + remote_major, remote_minor, remote_version); compat_datafellows(remote_version); mismatch = 0; - switch(remote_major) { + switch (remote_major) { case 1: if (remote_minor == 99 && (options.protocol & SSH_PROTO_2) && @@ -406,8 +448,6 @@ fatal("Protocol major versions differ: %d vs. %d", (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, remote_major); - if (compat20) - packet_set_ssh2_format(); /* Send our own protocol version identification. */ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, @@ -422,61 +462,37 @@ } /* defaults to 'no' */ -int -read_yes_or_no(const char *prompt, int defval) +static int +confirm(const char *prompt) { - char buf[1024]; - FILE *f; - int retval = -1; + const char *msg, *again = "Please type 'yes' or 'no': "; + char *p; + int ret = -1; if (options.batch_mode) return 0; - - if (isatty(STDIN_FILENO)) - f = stdin; - else - f = fopen(_PATH_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"); - strlcpy(buf, "no", sizeof buf); - } - /* 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; - else if (strcmp(buf, "no") == 0) - retval = 0; - else - fprintf(stderr, "Please type 'yes' or 'no'.\n"); - - if (retval != -1) { - if (f != stdin) - fclose(f); - return retval; - } + for (msg = prompt;;msg = again) { + p = read_passphrase(msg, RP_ECHO); + if (p == NULL || + (p[0] == '\0') || (p[0] == '\n') || + strncasecmp(p, "no", 2) == 0) + ret = 0; + if (strncasecmp(p, "yes", 3) == 0) + ret = 1; + if (p) + xfree(p); + if (ret != -1) + return ret; } } /* - * check whether the supplied host key is valid, return only if ok. + * check whether the supplied host key is valid, return -1 if the key + * is not valid. the user_hostfile will not be updated if 'readonly' is true. */ - -void +static int check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, - const char *user_hostfile, const char *system_hostfile) + int readonly, const char *user_hostfile, const char *system_hostfile) { Key *file_key; char *type = key_type(host_key); @@ -485,8 +501,10 @@ HostStatus host_status; HostStatus ip_status; int local = 0, host_ip_differ = 0; + int salen; char ntop[NI_MAXHOST]; - int host_line, ip_line; + char msg[1024]; + int len, host_line, ip_line; const char *host_file = NULL, *ip_file = NULL; /* @@ -500,19 +518,25 @@ /** hostaddr == 0! */ switch (hostaddr->sa_family) { case AF_INET: - local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; + local = (ntohl(((struct sockaddr_in *)hostaddr)-> + sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; + salen = sizeof(struct sockaddr_in); break; case AF_INET6: - local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); + local = IN6_IS_ADDR_LOOPBACK( + &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); + salen = sizeof(struct sockaddr_in6); break; default: local = 0; + salen = sizeof(struct sockaddr_storage); break; } - if (local && options.host_key_alias == NULL) { + if (options.no_host_authentication_for_localhost == 1 && local && + options.host_key_alias == NULL) { debug("Forcing accepting of host key for " "loopback/localhost."); - return; + return 0; } /* @@ -520,7 +544,7 @@ * using a proxy command */ if (options.proxy_command == NULL) { - if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop), + if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal("check_host_key: getnameinfo failed"); ip = xstrdup(ntop); @@ -556,10 +580,12 @@ * hosts or in the systemwide list. */ host_file = user_hostfile; - host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); + host_status = check_host_in_hostfile(host_file, host, host_key, + file_key, &host_line); if (host_status == HOST_NEW) { host_file = system_hostfile; - host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); + host_status = check_host_in_hostfile(host_file, host, host_key, + file_key, &host_line); } /* * Also perform check for the ip address, skip the check if we are @@ -569,10 +595,12 @@ Key *ip_key = key_new(host_key->type); ip_file = user_hostfile; - ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); + ip_status = check_host_in_hostfile(ip_file, ip, host_key, + ip_key, &ip_line); if (ip_status == HOST_NEW) { ip_file = system_hostfile; - ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); + ip_status = check_host_in_hostfile(ip_file, ip, + host_key, ip_key, &ip_line); } if (host_status == HOST_CHANGED && (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) @@ -591,32 +619,46 @@ host, type); debug("Found key in %s:%d", host_file, host_line); if (options.check_host_ip && ip_status == HOST_NEW) { - if (!add_host_to_hostfile(user_hostfile, ip, host_key)) - log("Failed to add the %s host key for IP address '%.128s' to the list of known hosts (%.30s).", - type, ip, user_hostfile); - else - log("Warning: Permanently added the %s host key for IP address '%.128s' to the list of known hosts.", + if (readonly) + log("%s host key for IP address " + "'%.128s' not in list of known hosts.", type, ip); + else if (!add_host_to_hostfile(user_hostfile, ip, + host_key)) + log("Failed to add the %s host key for IP " + "address '%.128s' to the list of known " + "hosts (%.30s).", type, ip, user_hostfile); + else + log("Warning: Permanently added the %s host " + "key for IP address '%.128s' to the list " + "of known hosts.", type, ip); } break; case HOST_NEW: + if (readonly) + goto fail; /* 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 %s host key is known for %.200s and you have requested strict checking.", type, host); + /* + * User has requested strict host key checking. We + * will not add the host key automatically. The only + * alternative left is to abort. + */ + error("No %s host key is known for %.200s and you " + "have requested strict checking.", type, host); + goto fail; } else if (options.strict_host_key_checking == 2) { /* The default */ - char prompt[1024]; fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - snprintf(prompt, sizeof(prompt), - "The authenticity of host '%.200s (%s)' can't be established.\n" + snprintf(msg, sizeof(msg), + "The authenticity of host '%.200s (%s)' can't be " + "established.\n" "%s key fingerprint is %s.\n" - "Are you sure you want to continue connecting (yes/no)? ", - host, ip, type, fp); + "Are you sure you want to continue connecting " + "(yes/no)? ", host, ip, type, fp); xfree(fp); - if (!read_yes_or_no(prompt, -1)) - fatal("Aborted by user!"); + if (!confirm(msg)) + goto fail; } if (options.check_host_ip && ip_status == HOST_NEW) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); @@ -624,13 +666,16 @@ } else hostp = host; - /* If not in strict mode, add the key automatically to the local known_hosts file. */ + /* + * If not in strict mode, add the key automatically to the + * local known_hosts file. + */ if (!add_host_to_hostfile(user_hostfile, hostp, host_key)) - log("Failed to add the host to the list of known hosts (%.500s).", - user_hostfile); + log("Failed to add the host to the list of known " + "hosts (%.500s).", user_hostfile); else - log("Warning: Permanently added '%.200s' (%s) to the list of known hosts.", - hostp, type); + log("Warning: Permanently added '%.200s' (%s) to the " + "list of known hosts.", hostp, type); break; case HOST_CHANGED: if (options.check_host_ip && host_ip_differ) { @@ -672,8 +717,11 @@ * 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("%s host key for %.200s has changed and you have requested strict checking.", type, host); + if (options.strict_host_key_checking) { + error("%s host key for %.200s has changed and you have " + "requested strict checking.", type, host); + goto fail; + } /* * If strict host key checking has not been requested, allow @@ -681,20 +729,26 @@ * agent forwarding. */ if (options.password_authentication) { - error("Password authentication is disabled to avoid trojan horses."); + error("Password authentication is disabled to avoid " + "man-in-the-middle attacks."); options.password_authentication = 0; } if (options.forward_agent) { - error("Agent forwarding is disabled to avoid trojan horses."); + error("Agent forwarding is disabled to avoid " + "man-in-the-middle attacks."); options.forward_agent = 0; } if (options.forward_x11) { - error("X11 forwarding is disabled to avoid trojan horses."); + error("X11 forwarding is disabled to avoid " + "man-in-the-middle attacks."); options.forward_x11 = 0; } - if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) { - error("Port forwarding is disabled to avoid trojan horses."); - options.num_local_forwards = options.num_remote_forwards = 0; + if (options.num_local_forwards > 0 || + options.num_remote_forwards > 0) { + error("Port forwarding is disabled to avoid " + "man-in-the-middle attacks."); + options.num_local_forwards = + options.num_remote_forwards = 0; } /* * XXX Should permit the user to change to use the new id. @@ -708,222 +762,54 @@ if (options.check_host_ip && host_status != HOST_CHANGED && ip_status == HOST_CHANGED) { - log("Warning: the %s host key for '%.200s' " - "differs from the key for the IP address '%.128s'", - type, host, ip); - if (host_status == HOST_OK) - log("Matching host key in %s:%d", host_file, host_line); - log("Offending key for IP in %s:%d", ip_file, ip_line); + snprintf(msg, sizeof(msg), + "Warning: the %s host key for '%.200s' " + "differs from the key for the IP address '%.128s'" + "\nOffending key for IP in %s:%d", + type, host, ip, ip_file, ip_line); + if (host_status == HOST_OK) { + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, + "\nMatching host key in %s:%d", + host_file, host_line); + } if (options.strict_host_key_checking == 1) { - fatal("Exiting, you have requested strict checking."); + log(msg); + error("Exiting, you have requested strict checking."); + goto fail; } else if (options.strict_host_key_checking == 2) { - if (!read_yes_or_no("Are you sure you want " \ - "to continue connecting (yes/no)? ", -1)) - fatal("Aborted by user!"); + strlcat(msg, "\nAre you sure you want " + "to continue connecting (yes/no)? ", sizeof(msg)); + if (!confirm(msg)) + goto fail; + } else { + log(msg); } } xfree(ip); + return 0; + +fail: + xfree(ip); + return -1; } -#ifdef KRB5 int -try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) +verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) { - krb5_error_code problem; - const char *tkfile; - struct stat buf; - krb5_ccache ccache = NULL; - const char *remotehost; - krb5_data ap; - int type, payload_len; - krb5_ap_rep_enc_part *reply = NULL; - int ret; - - memset(&ap, 0, sizeof(ap)); - - problem = krb5_init_context(context); - if (problem) { - ret = 0; - goto out; - } - - tkfile = krb5_cc_default_name(*context); - if (strncmp(tkfile, "FILE:", 5) == 0) - tkfile += 5; - - if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { - debug("Kerberos V5: could not get default ccache (permission denied)."); - ret = 0; - goto out; - } - - problem = krb5_cc_default(*context, &ccache); - if (problem) { - ret = 0; - goto out; - } - - remotehost = get_canonical_hostname(1); - - problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED, - "host", remotehost, NULL, ccache, &ap); - if (problem) { - ret = 0; - goto out; - } - - packet_start(SSH_CMSG_AUTH_KERBEROS); - packet_put_string((char *) ap.data, ap.length); - packet_send(); - packet_write_wait(); - - xfree(ap.data); - ap.length = 0; - - type = packet_read(&payload_len); - switch (type) { - case SSH_SMSG_FAILURE: - /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ - debug("Kerberos V5 authentication failed."); - ret = 0; - break; - - case SSH_SMSG_AUTH_KERBEROS_RESPONSE: - /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ - debug("Kerberos V5 authentication accepted."); - - /* Get server's response. */ - ap.data = packet_get_string((unsigned int *) &ap.length); - - packet_integrity_check(payload_len, 4 + ap.length, type); - /* XXX je to dobre? */ - - problem = krb5_rd_rep(*context, *auth_context, &ap, &reply); - if (problem) { - ret = 0; - goto out; - } - ret = 1; - break; - - default: - packet_disconnect("Protocol error on Kerberos V5 response: %d", type); - ret = 0; - break; + struct stat st; - } - -out: - if (ccache != NULL) - krb5_cc_close(*context, ccache); - if (reply != NULL) - krb5_free_ap_rep_enc_part(*context, reply); - if (ap.length > 0) - krb5_data_free(&ap); - - return ret; - -} - -void -send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) -{ - int fd; - int type, payload_len; - krb5_error_code problem; - krb5_data outbuf; - krb5_ccache ccache = NULL; - krb5_creds creds; - krb5_kdc_flags flags; - const char *remotehost = get_canonical_hostname(1); - - memset(&creds, 0, sizeof(creds)); - memset(&outbuf, 0, sizeof(outbuf)); - - fd = packet_get_connection_in(); - problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd); - if (problem) { - goto out; - } - -#if 0 - tkfile = krb5_cc_default_name(context); - if (strncmp(tkfile, "FILE:", 5) == 0) - tkfile += 5; - - if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { - debug("Kerberos V5: could not get default ccache (permission denied)."); - goto out; - } -#endif - - problem = krb5_cc_default(context, &ccache); - if (problem) { - goto out; - } - - problem = krb5_cc_get_principal(context, ccache, &creds.client); - if (problem) { - goto out; - } - - problem = krb5_build_principal(context, &creds.server, - strlen(creds.client->realm), - creds.client->realm, - "krbtgt", - creds.client->realm, - NULL); - if (problem) { - goto out; - } - - creds.times.endtime = 0; - - flags.i = 0; - flags.b.forwarded = 1; - flags.b.forwardable = krb5_config_get_bool(context, NULL, - "libdefaults", "forwardable", NULL); - - problem = krb5_get_forwarded_creds (context, - auth_context, - ccache, - flags.i, - remotehost, - &creds, - &outbuf); - if (problem) { - goto out; - } - - packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); - packet_put_string((char *)outbuf.data, outbuf.length); - packet_send(); - packet_write_wait(); - - type = packet_read(&payload_len); - switch (type) { - case SSH_SMSG_SUCCESS: - break; - case SSH_SMSG_FAILURE: - break; - default: - break; - } - -out: - if (creds.client) - krb5_free_principal(context, creds.client); - if (creds.server) - krb5_free_principal(context, creds.server); - if (ccache) - krb5_cc_close(context, ccache); - if (outbuf.data) - xfree(outbuf.data); - - return; + /* return ok if the key can be found in an old keyfile */ + if (stat(options.system_hostfile2, &st) == 0 || + stat(options.user_hostfile2, &st) == 0) { + if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1, + options.user_hostfile2, options.system_hostfile2) == 0) + return 0; + } + return check_host_key(host, hostaddr, host_key, /*readonly*/ 0, + options.user_hostfile, options.system_hostfile); } -#endif /* KRB5 */ /* * Starts a dialog with the server, and authenticates the current user on the @@ -933,7 +819,7 @@ * This function does not require super-user privileges. */ void -ssh_login(Key **keys, int nkeys, const char *orighost, +ssh_login(Sensitive *sensitive, const char *orighost, struct sockaddr *hostaddr, struct passwd *pw) { char *host, *cp; @@ -958,10 +844,10 @@ /* authenticate user */ if (compat20) { ssh_kex2(host, hostaddr); - ssh_userauth2(local_user, server_user, host, keys, nkeys); + ssh_userauth2(local_user, server_user, host, sensitive); } else { ssh_kex(host, hostaddr); - ssh_userauth1(local_user, server_user, host, keys, nkeys); + ssh_userauth1(local_user, server_user, host, sensitive); } } @@ -972,7 +858,7 @@ char *padded; if (datafellows & SSH_BUG_PASSWORDPAD) { - packet_put_string(password, strlen(password)); + packet_put_cstring(password); return; } size = roundup(strlen(password) + 1, 32); Index: src/crypto/openssh/sshconnect.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshconnect.h,v retrieving revision 1.1.1.1.2.5 diff -u -u -r1.1.1.1.2.5 sshconnect.h --- src/crypto/openssh/sshconnect.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.5 +++ src/crypto/openssh/sshconnect.h 30 Jun 2002 11:38:01 -0000 @@ -1,5 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.9 2001/04/12 19:15:25 markus Exp $ */ -/* $FreeBSD: src/crypto/openssh/sshconnect.h,v 1.1.1.1.2.5 2001/09/28 01:33:35 green Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.17 2002/06/19 00:27:55 deraadt Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -27,30 +26,44 @@ #ifndef SSHCONNECT_H #define SSHCONNECT_H +typedef struct Sensitive Sensitive; +struct Sensitive { + Key **keys; + int nkeys; + int external_keysign; +}; + int -ssh_connect(const char *host, struct sockaddr_storage * hostaddr, - u_short port, int connection_attempts, - int anonymous, struct passwd *pw, - const char *proxy_command); +ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int, + int, const char *); void -ssh_login(Key **keys, int nkeys, const char *orighost, - struct sockaddr *hostaddr, struct passwd *pw); +ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *); -void -check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, - const char *user_hostfile, const char *system_hostfile); +int verify_host_key(char *, struct sockaddr *, Key *); -void ssh_kex(char *host, struct sockaddr *hostaddr); -void ssh_kex2(char *host, struct sockaddr *hostaddr); +void ssh_kex(char *, struct sockaddr *); +void ssh_kex2(char *, struct sockaddr *); -void -ssh_userauth1(const char *local_user, const char *server_user, char *host, - Key **keys, int nkeys); -void -ssh_userauth2(const char *local_user, const char *server_user, char *host, - Key **keys, int nkeys); +void ssh_userauth1(const char *, const char *, char *, Sensitive *); +void ssh_userauth2(const char *, const char *, char *, Sensitive *); -void ssh_put_password(char *password); +void ssh_put_password(char *); + + +/* + * Macros to raise/lower permissions. + */ +#define PRIV_START do { \ + int save_errno = errno; \ + (void)seteuid(original_effective_uid); \ + errno = save_errno; \ +} while (0) + +#define PRIV_END do { \ + int save_errno = errno; \ + (void)seteuid(original_real_uid); \ + errno = save_errno; \ +} while (0) #endif Index: src/crypto/openssh/sshconnect1.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshconnect1.c,v retrieving revision 1.2.2.7 diff -u -u -r1.2.2.7 sshconnect1.c --- src/crypto/openssh/sshconnect1.c 28 Sep 2001 01:33:35 -0000 1.2.2.7 +++ src/crypto/openssh/sshconnect1.c 30 Jun 2002 11:38:01 -0000 @@ -13,15 +13,20 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.31 2001/04/17 08:14:01 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/sshconnect1.c,v 1.2.2.7 2001/09/28 01:33:35 green Exp $"); +RCSID("$OpenBSD: sshconnect1.c,v 1.51 2002/05/23 19:24:30 markus Exp $"); #include -#include +#include #ifdef KRB4 #include #endif +#ifdef KRB5 +#include +#ifndef HEIMDAL +#define krb5_get_err_text(context,code) error_message(code) +#endif /* !HEIMDAL */ +#endif #ifdef AFS #include #include "radix.h" @@ -57,7 +62,7 @@ * Checks if the user has an authentication agent, and if so, tries to * authenticate using the agent. */ -int +static int try_agent_authentication(void) { int type; @@ -65,7 +70,6 @@ AuthenticationConnection *auth; u_char response[16]; u_int i; - int plen, clen; Key *key; BIGNUM *challenge; @@ -74,12 +78,12 @@ if (!auth) return 0; - challenge = BN_new(); - + if ((challenge = BN_new()) == NULL) + fatal("try_agent_authentication: BN_new failed"); /* Loop through identities served by the agent. */ for (key = ssh_get_first_identity(auth, &comment, 1); - key != NULL; - key = ssh_get_next_identity(auth, &comment, 1)) { + key != NULL; + key = ssh_get_next_identity(auth, &comment, 1)) { /* Try this identity. */ debug("Trying RSA authentication via agent with '%.100s'", comment); @@ -92,7 +96,7 @@ packet_write_wait(); /* Wait for server's response. */ - type = packet_read(&plen); + type = packet_read(); /* The server sends failure if it doesn\'t like our key or does not support RSA authentication. */ @@ -106,9 +110,8 @@ packet_disconnect("Protocol error during RSA authentication: %d", type); - packet_get_bignum(challenge, &clen); - - packet_integrity_check(plen, clen, type); + packet_get_bignum(challenge); + packet_check_eom(); debug("Received RSA challenge from server."); @@ -133,7 +136,7 @@ packet_write_wait(); /* Wait for response from the server. */ - type = packet_read(&plen); + type = packet_read(); /* The server returns success if it accepted the authentication. */ if (type == SSH_SMSG_SUCCESS) { @@ -157,7 +160,7 @@ * Computes the proper response to a RSA challenge, and sends the response to * the server. */ -void +static void respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) { u_char buf[32], response[16]; @@ -202,23 +205,18 @@ * Checks if the user has authentication file, and if so, tries to authenticate * the user using it. */ -int -try_rsa_authentication(const char *authfile) +static int +try_rsa_authentication(int idx) { BIGNUM *challenge; - Key *public; - Key *private; - char *passphrase, *comment; - int type, i; - int plen, clen; + Key *public, *private; + char buf[300], *passphrase, *comment, *authfile; + int i, type, quit; + + public = options.identity_keys[idx]; + authfile = options.identity_files[idx]; + comment = xstrdup(authfile); - /* Try to load identification for the authentication key. */ - /* XXKEYLOAD */ - public = key_load_public_type(KEY_RSA1, authfile, &comment); - if (public == NULL) { - /* Could not load it. Fail. */ - return 0; - } debug("Trying RSA authentication with key '%.100s'", comment); /* Tell the server that we are willing to authenticate using this key. */ @@ -227,11 +225,8 @@ packet_send(); packet_write_wait(); - /* We no longer need the public key. */ - key_free(public); - /* Wait for server's response. */ - type = packet_read(&plen); + type = packet_read(); /* * The server responds with failure if it doesn\'t like our key or @@ -247,68 +242,74 @@ packet_disconnect("Protocol error during RSA authentication: %d", type); /* Get the challenge from the packet. */ - challenge = BN_new(); - packet_get_bignum(challenge, &clen); - - packet_integrity_check(plen, clen, type); + if ((challenge = BN_new()) == NULL) + fatal("try_rsa_authentication: BN_new failed"); + packet_get_bignum(challenge); + packet_check_eom(); debug("Received RSA challenge from server."); /* - * Load the private key. Try first with empty passphrase; if it + * If the key is not stored in external hardware, we have to + * load the private key. Try first with empty passphrase; if it * fails, ask for a passphrase. */ - private = key_load_private_type(KEY_RSA1, authfile, "", NULL); - if (private == NULL) { - char buf[300]; - snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ", - comment); - if (!options.batch_mode) + if (public->flags && KEY_FLAG_EXT) + private = public; + else + private = key_load_private_type(KEY_RSA1, authfile, "", NULL); + if (private == NULL && !options.batch_mode) { + snprintf(buf, sizeof(buf), + "Enter passphrase for RSA key '%.100s': ", comment); + for (i = 0; i < options.number_of_password_prompts; i++) { 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. */ - private = key_load_private_type(KEY_RSA1, authfile, passphrase, NULL); - if (private == NULL) { + if (strcmp(passphrase, "") != 0) { + private = key_load_private_type(KEY_RSA1, + authfile, passphrase, NULL); + quit = 0; + } else { + debug2("no passphrase given, try next key"); + quit = 1; + } 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); - BN_clear_free(challenge); - return 0; + if (private != NULL || quit) + break; + debug2("bad passphrase given, try again..."); } - /* Destroy the passphrase. */ - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); } /* We no longer need the comment. */ xfree(comment); + if (private == NULL) { + if (!options.batch_mode) + 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(SSH_SMSG_FAILURE); + BN_clear_free(challenge); + return 0; + } + /* Compute and send a response to the challenge. */ respond_to_rsa_challenge(challenge, private->rsa); - /* Destroy the private key. */ - key_free(private); + /* Destroy the private key unless it in external hardware. */ + if (!(private->flags & KEY_FLAG_EXT)) + key_free(private); /* We no longer need the challenge. */ BN_clear_free(challenge); /* Wait for response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { debug("RSA authentication accepted by server."); return 1; @@ -323,18 +324,17 @@ * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv * authentication and RSA host authentication. */ -int +static int try_rhosts_rsa_authentication(const char *local_user, Key * host_key) { int type; BIGNUM *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_cstring(local_user); packet_put_int(BN_num_bits(host_key->rsa->n)); packet_put_bignum(host_key->rsa->e); packet_put_bignum(host_key->rsa->n); @@ -342,7 +342,7 @@ packet_write_wait(); /* Wait for server's response. */ - type = packet_read(&plen); + type = packet_read(); /* The server responds with failure if it doesn't admit our .rhosts authentication or doesn't know our host key. */ @@ -355,10 +355,10 @@ packet_disconnect("Protocol error during RSA authentication: %d", type); /* Get the challenge from the packet. */ - challenge = BN_new(); - packet_get_bignum(challenge, &clen); - - packet_integrity_check(plen, clen, type); + if ((challenge = BN_new()) == NULL) + fatal("try_rhosts_rsa_authentication: BN_new failed"); + packet_get_bignum(challenge); + packet_check_eom(); debug("Received RSA challenge for host key from server."); @@ -369,7 +369,7 @@ BN_clear_free(challenge); /* Wait for response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server."); return 1; @@ -381,7 +381,7 @@ } #ifdef KRB4 -int +static int try_krb4_authentication(void) { KTEXT_ST auth; /* Kerberos data */ @@ -389,7 +389,7 @@ char inst[INST_SZ]; char *realm; CREDENTIALS cred; - int r, type, plen; + int r, type; socklen_t slen; Key_schedule schedule; u_long checksum, cksum; @@ -401,19 +401,20 @@ if (stat(tkt_string(), &st) < 0) return 0; - strncpy(inst, (char *) krb_get_phost(get_canonical_hostname(1)), INST_SZ); + strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)), + INST_SZ); - realm = (char *) krb_realmofhost(get_canonical_hostname(1)); + realm = (char *)krb_realmofhost(get_canonical_hostname(1)); if (!realm) { - debug("Kerberos V4: no realm for %s", get_canonical_hostname(1)); + debug("Kerberos v4: no realm for %s", get_canonical_hostname(1)); return 0; } /* This can really be anything. */ - checksum = (u_long) getpid(); + 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: %s", krb_err_txt[r]); + debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]); return 0; } /* Get session key to decrypt the server's reply with. */ @@ -436,35 +437,37 @@ slen = sizeof(local); memset(&local, 0, sizeof(local)); if (getsockname(packet_get_connection_in(), - (struct sockaddr *) & local, &slen) < 0) + (struct sockaddr *)&local, &slen) < 0) debug("getsockname failed: %s", strerror(errno)); slen = sizeof(foreign); memset(&foreign, 0, sizeof(foreign)); if (getpeername(packet_get_connection_in(), - (struct sockaddr *) & foreign, &slen) < 0) { + (struct sockaddr *)&foreign, &slen) < 0) { debug("getpeername failed: %s", strerror(errno)); fatal_cleanup(); } /* Get server reply. */ - type = packet_read(&plen); + type = packet_read(); switch (type) { case SSH_SMSG_FAILURE: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ - debug("Kerberos V4 authentication failed."); + debug("Kerberos v4 authentication failed."); return 0; break; case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ - debug("Kerberos V4 authentication accepted."); + debug("Kerberos v4 authentication accepted."); /* Get server's response. */ reply = packet_get_string((u_int *) &auth.length); + if (auth.length >= MAX_KTXT_LEN) + fatal("Kerberos v4: Malformed response from server"); memcpy(auth.dat, reply, auth.length); xfree(reply); - packet_integrity_check(plen, 4 + auth.length, type); + packet_check_eom(); /* * If his response isn't properly encrypted with the session @@ -472,84 +475,318 @@ * bogus. Bail out. */ r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session, - &foreign, &local, &msg_data); + &foreign, &local, &msg_data); if (r != KSUCCESS) { - debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]); - packet_disconnect("Kerberos V4 challenge failed!"); + debug("Kerberos v4 krb_rd_priv failed: %s", + 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)); + 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."); + debug("Kerberos v4 challenge successful."); return 1; } else - packet_disconnect("Kerberos V4 challenge failed!"); + packet_disconnect("Kerberos v4 challenge failed!"); break; default: - packet_disconnect("Protocol error on Kerberos V4 response: %d", type); + packet_disconnect("Protocol error on Kerberos v4 response: %d", type); } return 0; } #endif /* KRB4 */ +#ifdef KRB5 +static int +try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) +{ + krb5_error_code problem; + const char *tkfile; + struct stat buf; + krb5_ccache ccache = NULL; + const char *remotehost; + krb5_data ap; + int type; + krb5_ap_rep_enc_part *reply = NULL; + int ret; + + memset(&ap, 0, sizeof(ap)); + + problem = krb5_init_context(context); + if (problem) { + debug("Kerberos v5: krb5_init_context failed"); + ret = 0; + goto out; + } + + problem = krb5_auth_con_init(*context, auth_context); + if (problem) { + debug("Kerberos v5: krb5_auth_con_init failed"); + ret = 0; + goto out; + } + +#ifndef HEIMDAL + problem = krb5_auth_con_setflags(*context, *auth_context, + KRB5_AUTH_CONTEXT_RET_TIME); + if (problem) { + debug("Keberos v5: krb5_auth_con_setflags failed"); + ret = 0; + goto out; + } +#endif + + tkfile = krb5_cc_default_name(*context); + if (strncmp(tkfile, "FILE:", 5) == 0) + tkfile += 5; + + if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { + debug("Kerberos v5: could not get default ccache (permission denied)."); + ret = 0; + goto out; + } + + problem = krb5_cc_default(*context, &ccache); + if (problem) { + debug("Kerberos v5: krb5_cc_default failed: %s", + krb5_get_err_text(*context, problem)); + ret = 0; + goto out; + } + + remotehost = get_canonical_hostname(1); + + problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED, + "host", remotehost, NULL, ccache, &ap); + if (problem) { + debug("Kerberos v5: krb5_mk_req failed: %s", + krb5_get_err_text(*context, problem)); + ret = 0; + goto out; + } + + packet_start(SSH_CMSG_AUTH_KERBEROS); + packet_put_string((char *) ap.data, ap.length); + packet_send(); + packet_write_wait(); + + xfree(ap.data); + ap.length = 0; + + type = packet_read(); + switch (type) { + case SSH_SMSG_FAILURE: + /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ + debug("Kerberos v5 authentication failed."); + ret = 0; + break; + + case SSH_SMSG_AUTH_KERBEROS_RESPONSE: + /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ + debug("Kerberos v5 authentication accepted."); + + /* Get server's response. */ + ap.data = packet_get_string((unsigned int *) &ap.length); + packet_check_eom(); + /* XXX je to dobre? */ + + problem = krb5_rd_rep(*context, *auth_context, &ap, &reply); + if (problem) { + ret = 0; + } + ret = 1; + break; + + default: + packet_disconnect("Protocol error on Kerberos v5 response: %d", + type); + ret = 0; + break; + + } + + out: + if (ccache != NULL) + krb5_cc_close(*context, ccache); + if (reply != NULL) + krb5_free_ap_rep_enc_part(*context, reply); + if (ap.length > 0) +#ifdef HEIMDAL + krb5_data_free(&ap); +#else + krb5_free_data_contents(*context, &ap); +#endif + + return (ret); +} + +static void +send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) +{ + int fd, type; + krb5_error_code problem; + krb5_data outbuf; + krb5_ccache ccache = NULL; + krb5_creds creds; +#ifdef HEIMDAL + krb5_kdc_flags flags; +#else + int forwardable; +#endif + const char *remotehost; + + memset(&creds, 0, sizeof(creds)); + memset(&outbuf, 0, sizeof(outbuf)); + + fd = packet_get_connection_in(); + +#ifdef HEIMDAL + problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd); +#else + problem = krb5_auth_con_genaddrs(context, auth_context, fd, + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR | + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR); +#endif + if (problem) + goto out; + + problem = krb5_cc_default(context, &ccache); + if (problem) + goto out; + + problem = krb5_cc_get_principal(context, ccache, &creds.client); + if (problem) + goto out; + + remotehost = get_canonical_hostname(1); + +#ifdef HEIMDAL + problem = krb5_build_principal(context, &creds.server, + strlen(creds.client->realm), creds.client->realm, + "krbtgt", creds.client->realm, NULL); +#else + problem = krb5_build_principal(context, &creds.server, + creds.client->realm.length, creds.client->realm.data, + "host", remotehost, NULL); +#endif + if (problem) + goto out; + + creds.times.endtime = 0; + +#ifdef HEIMDAL + flags.i = 0; + flags.b.forwarded = 1; + flags.b.forwardable = krb5_config_get_bool(context, NULL, + "libdefaults", "forwardable", NULL); + problem = krb5_get_forwarded_creds(context, auth_context, + ccache, flags.i, remotehost, &creds, &outbuf); +#else + forwardable = 1; + problem = krb5_fwd_tgt_creds(context, auth_context, remotehost, + creds.client, creds.server, ccache, forwardable, &outbuf); +#endif + + if (problem) + goto out; + + packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); + packet_put_string((char *)outbuf.data, outbuf.length); + packet_send(); + packet_write_wait(); + + type = packet_read(); + + if (type == SSH_SMSG_SUCCESS) { + char *pname; + + krb5_unparse_name(context, creds.client, &pname); + debug("Kerberos v5 TGT forwarded (%s).", pname); + xfree(pname); + } else + debug("Kerberos v5 TGT forwarding failed."); + + return; + + out: + if (problem) + debug("Kerberos v5 TGT forwarding failed: %s", + krb5_get_err_text(context, problem)); + if (creds.client) + krb5_free_principal(context, creds.client); + if (creds.server) + krb5_free_principal(context, creds.server); + if (ccache) + krb5_cc_close(context, ccache); + if (outbuf.data) + xfree(outbuf.data); +} +#endif /* KRB5 */ + #ifdef AFS -int +static void send_krb4_tgt(void) { CREDENTIALS *creds; - char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; - int r, type, plen; - char buffer[8192]; struct stat st; + char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; + int problem, type; /* Don't do anything if we don't have any tickets. */ if (stat(tkt_string(), &st) < 0) - return 0; + return; creds = xmalloc(sizeof(*creds)); - if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) { - debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]); - return 0; - } - if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) { - debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]); - return 0; - } + problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm); + if (problem) + goto out; + + problem = krb_get_cred("krbtgt", prealm, prealm, creds); + if (problem) + goto out; + if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) { - debug("Kerberos V4 ticket expired: %s", TKT_FILE); - return 0; + problem = RD_AP_EXP; + goto out; } - creds_to_radix(creds, (u_char *)buffer, sizeof buffer); - xfree(creds); + creds_to_radix(creds, (u_char *)buffer, sizeof(buffer)); - packet_start(SSH_CMSG_HAVE_KRB4_TGT); - packet_put_string(buffer, strlen(buffer)); + packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); + packet_put_cstring(buffer); packet_send(); packet_write_wait(); - type = packet_read(&plen); + type = packet_read(); - if (type == SSH_SMSG_FAILURE) - debug("Kerberos TGT for realm %s rejected.", prealm); - else if (type != SSH_SMSG_SUCCESS) - packet_disconnect("Protocol error on Kerberos TGT response: %d", type); + if (type == SSH_SMSG_SUCCESS) + debug("Kerberos v4 TGT forwarded (%s%s%s@%s).", + creds->pname, creds->pinst[0] ? "." : "", + creds->pinst, creds->realm); + else + debug("Kerberos v4 TGT rejected."); - return 1; + xfree(creds); + return; + + out: + debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]); + xfree(creds); } -void +static void send_afs_tokens(void) { CREDENTIALS creds; struct ViceIoctl parms; struct ClearToken ct; - int i, type, len, plen; + int i, type, len; char buf[2048], *p, *server_cell; char buffer[8192]; @@ -582,27 +819,29 @@ server_cell = p; /* Flesh out our credentials. */ - strlcpy(creds.service, "afs", sizeof creds.service); + strlcpy(creds.service, "afs", sizeof(creds.service)); creds.instance[0] = '\0'; strlcpy(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.lifetime = krb_time_to_life(creds.issue_date, + ct.EndTimestamp); creds.kvno = ct.AuthHandle; snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId); creds.pinst[0] = '\0'; /* Encode token, ship it off. */ - if (creds_to_radix(&creds, (u_char *) buffer, sizeof buffer) <= 0) + if (creds_to_radix(&creds, (u_char *)buffer, + sizeof(buffer)) <= 0) break; packet_start(SSH_CMSG_HAVE_AFS_TOKEN); - packet_put_string(buffer, strlen(buffer)); + packet_put_cstring(buffer); packet_send(); packet_write_wait(); /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_FAILURE) debug("AFS token for cell %s rejected.", server_cell); @@ -617,43 +856,42 @@ * Tries to authenticate with any string-based challenge/response system. * Note that the client code is not tied to s/key or TIS. */ -int -try_challenge_reponse_authentication(void) +static int +try_challenge_response_authentication(void) { int type, i; - int payload_len; u_int clen; char prompt[1024]; char *challenge, *response; - debug("Doing challenge reponse authentication."); + debug("Doing challenge response authentication."); - /* request a challenge */ - packet_start(SSH_CMSG_AUTH_TIS); - packet_send(); - packet_write_wait(); - - type = packet_read(&payload_len); - if (type != SSH_SMSG_FAILURE && - type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - packet_disconnect("Protocol error: got %d in response " - "to skey-auth", type); - } - if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - debug("No challenge for skey authentication."); - return 0; - } - challenge = packet_get_string(&clen); - packet_integrity_check(payload_len, (4 + clen), type); - snprintf(prompt, sizeof prompt, "%s%s", challenge, - strchr(challenge, '\n') ? "" : "\nResponse: "); - xfree(challenge); for (i = 0; i < options.number_of_password_prompts; i++) { + /* request a challenge */ + packet_start(SSH_CMSG_AUTH_TIS); + packet_send(); + packet_write_wait(); + + type = packet_read(); + if (type != SSH_SMSG_FAILURE && + type != SSH_SMSG_AUTH_TIS_CHALLENGE) { + packet_disconnect("Protocol error: got %d in response " + "to SSH_CMSG_AUTH_TIS", type); + } + if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { + debug("No challenge."); + return 0; + } + challenge = packet_get_string(&clen); + packet_check_eom(); + snprintf(prompt, sizeof prompt, "%s%s", challenge, + strchr(challenge, '\n') ? "" : "\nResponse: "); + xfree(challenge); if (i != 0) error("Permission denied, please try again."); if (options.cipher == SSH_CIPHER_NONE) log("WARNING: Encryption is disabled! " - "Reponse will be transmitted in clear text."); + "Response will be transmitted in clear text."); response = read_passphrase(prompt, 0); if (strcmp(response, "") == 0) { xfree(response); @@ -665,7 +903,7 @@ xfree(response); packet_send(); packet_write_wait(); - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) return 1; if (type != SSH_SMSG_FAILURE) @@ -679,10 +917,10 @@ /* * Tries to authenticate with plain passwd authentication. */ -int +static int try_password_authentication(char *prompt) { - int type, i, payload_len; + int type, i; char *password; debug("Doing password authentication."); @@ -699,7 +937,7 @@ packet_send(); packet_write_wait(); - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) return 1; if (type != SSH_SMSG_FAILURE) @@ -717,54 +955,43 @@ { int i; BIGNUM *key; - RSA *host_key; - RSA *public_key; - Key k; + Key *host_key, *server_key; int bits, rbits; int ssh_cipher_default = SSH_CIPHER_3DES; u_char session_key[SSH_SESSION_KEY_LENGTH]; u_char cookie[8]; u_int supported_ciphers; u_int server_flags, client_flags; - int payload_len, clen, sum_len = 0; u_int32_t rand = 0; debug("Waiting for server public key."); /* Wait for a public key packet from the server. */ - packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY); + packet_read_expect(SSH_SMSG_PUBLIC_KEY); /* Get cookie from the packet. */ for (i = 0; i < 8; i++) cookie[i] = packet_get_char(); /* Get the public key. */ - public_key = RSA_new(); - bits = packet_get_int();/* bits */ - public_key->e = BN_new(); - packet_get_bignum(public_key->e, &clen); - sum_len += clen; - public_key->n = BN_new(); - packet_get_bignum(public_key->n, &clen); - sum_len += clen; + server_key = key_new(KEY_RSA1); + bits = packet_get_int(); + packet_get_bignum(server_key->rsa->e); + packet_get_bignum(server_key->rsa->n); - rbits = BN_num_bits(public_key->n); + rbits = BN_num_bits(server_key->rsa->n); if (bits != rbits) { log("Warning: Server lies about size of server public key: " "actual size is %d bits vs. announced %d.", rbits, bits); log("Warning: This may be due to an old implementation of ssh."); } /* Get the host key. */ - host_key = RSA_new(); - bits = packet_get_int();/* bits */ - host_key->e = BN_new(); - packet_get_bignum(host_key->e, &clen); - sum_len += clen; - host_key->n = BN_new(); - packet_get_bignum(host_key->n, &clen); - sum_len += clen; + host_key = key_new(KEY_RSA1); + bits = packet_get_int(); + packet_get_bignum(host_key->rsa->e); + packet_get_bignum(host_key->rsa->n); - rbits = BN_num_bits(host_key->n); + rbits = BN_num_bits(host_key->rsa->n); if (bits != rbits) { log("Warning: Server lies about size of server host key: " "actual size is %d bits vs. announced %d.", rbits, bits); @@ -777,21 +1004,17 @@ supported_ciphers = packet_get_int(); supported_authentications = packet_get_int(); + packet_check_eom(); debug("Received server public key (%d bits) and host key (%d bits).", - BN_num_bits(public_key->n), BN_num_bits(host_key->n)); + BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); - packet_integrity_check(payload_len, - 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, - SSH_SMSG_PUBLIC_KEY); - k.type = KEY_RSA1; - k.rsa = host_key; - check_host_key(host, hostaddr, &k, - options.user_hostfile, options.system_hostfile); + if (verify_host_key(host, hostaddr, host_key) == -1) + fatal("Host key verification failed."); client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; - compute_session_id(session_id, cookie, host_key->n, public_key->n); + compute_session_id(session_id, cookie, host_key->rsa->n, server_key->rsa->n); /* Generate a session key. */ arc4random_stir(); @@ -813,7 +1036,8 @@ * is the highest byte of the integer. The session key is xored with * the first 16 bytes of the session id. */ - key = BN_new(); + if ((key = BN_new()) == NULL) + fatal("respond_to_rsa_challenge: BN_new failed"); BN_set_word(key, 0); for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { BN_lshift(key, key, 8); @@ -827,35 +1051,35 @@ * Encrypt the integer using the public key and host key of the * server (key with smaller modulus first). */ - if (BN_cmp(public_key->n, host_key->n) < 0) { + if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) { /* Public key has smaller modulus. */ - if (BN_num_bits(host_key->n) < - BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: host_key %d < public_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(host_key->n), - BN_num_bits(public_key->n), - SSH_KEY_BITS_RESERVED); + if (BN_num_bits(host_key->rsa->n) < + BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("respond_to_rsa_challenge: host_key %d < server_key %d + " + "SSH_KEY_BITS_RESERVED %d", + BN_num_bits(host_key->rsa->n), + BN_num_bits(server_key->rsa->n), + SSH_KEY_BITS_RESERVED); } - rsa_public_encrypt(key, key, public_key); - rsa_public_encrypt(key, key, host_key); + rsa_public_encrypt(key, key, server_key->rsa); + rsa_public_encrypt(key, key, host_key->rsa); } else { /* Host key has smaller modulus (or they are equal). */ - if (BN_num_bits(public_key->n) < - BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: public_key %d < host_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(public_key->n), - BN_num_bits(host_key->n), - SSH_KEY_BITS_RESERVED); + if (BN_num_bits(server_key->rsa->n) < + BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("respond_to_rsa_challenge: server_key %d < host_key %d + " + "SSH_KEY_BITS_RESERVED %d", + BN_num_bits(server_key->rsa->n), + BN_num_bits(host_key->rsa->n), + SSH_KEY_BITS_RESERVED); } - rsa_public_encrypt(key, key, host_key); - rsa_public_encrypt(key, key, public_key); + rsa_public_encrypt(key, key, host_key->rsa); + rsa_public_encrypt(key, key, server_key->rsa); } /* Destroy the public keys since we no longer need them. */ - RSA_free(public_key); - RSA_free(host_key); + key_free(server_key); + key_free(host_key); if (options.cipher == SSH_CIPHER_NOT_SET) { if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default)) @@ -869,7 +1093,7 @@ /* 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)); + cipher_name(options.cipher)); debug("Encryption type: %.100s", cipher_name(options.cipher)); @@ -904,7 +1128,7 @@ * 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); + packet_read_expect(SSH_SMSG_SUCCESS); debug("Received encrypted confirmation."); } @@ -914,17 +1138,20 @@ */ void ssh_userauth1(const char *local_user, const char *server_user, char *host, - Key **keys, int nkeys) + Sensitive *sensitive) { +#ifdef KRB5 + krb5_context context = NULL; + krb5_auth_context auth_context = NULL; +#endif int i, type; - int payload_len; if (supported_authentications == 0) fatal("ssh_userauth1: server supports no auth methods"); /* 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_put_cstring(server_user); packet_send(); packet_write_wait(); @@ -933,77 +1160,44 @@ * needed (the user has no password). Otherwise the server responds * with failure. */ - type = packet_read(&payload_len); + type = packet_read(); /* check whether the connection was accepted without authentication. */ if (type == SSH_SMSG_SUCCESS) - return; + goto success; if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", - type); + packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type); #ifdef KRB5 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && - options.kerberos_authentication){ - krb5_context ssh_context = NULL; - krb5_auth_context auth_context = NULL; - - debug("Trying Kerberos V5 authentication."); - - if (try_krb5_authentication(&ssh_context, &auth_context)) { - type = packet_read(&payload_len); - if (type == SSH_SMSG_SUCCESS) { - if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && - options.krb5_tgt_passing) { - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); - send_krb5_tgt(ssh_context, auth_context); - - } - krb5_auth_con_free(ssh_context, auth_context); - krb5_free_context(ssh_context); - return; - } - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to Kerberos5 auth", type); + options.kerberos_authentication) { + debug("Trying Kerberos v5 authentication."); + if (try_krb5_authentication(&context, &auth_context)) { + type = packet_read(); + if (type == SSH_SMSG_SUCCESS) + goto success; + if (type != SSH_SMSG_FAILURE) + packet_disconnect("Protocol error: got %d in response to Kerberos v5 auth", type); + } } - } #endif /* KRB5 */ -#ifdef AFS - /* Try Kerberos tgt passing if the server supports it. */ - if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && - options.krb4_tgt_passing) { - if (options.cipher == SSH_CIPHER_NONE) - log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); - (void) send_krb4_tgt(); - } - /* 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 */ - #ifdef KRB4 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && options.kerberos_authentication) { - debug("Trying Kerberos authentication."); + debug("Trying Kerberos v4 authentication."); + if (try_krb4_authentication()) { - /* The server should respond with success or failure. */ - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) - return; + goto success; if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to Kerberos auth", type); + packet_disconnect("Protocol error: got %d in response to Kerberos v4 auth", type); } } #endif /* KRB4 */ - /* * Use rhosts authentication if running in privileged socket and we * do not wish to remain anonymous. @@ -1012,14 +1206,14 @@ options.rhosts_authentication) { debug("Trying rhosts authentication."); packet_start(SSH_CMSG_AUTH_RHOSTS); - packet_put_string(local_user, strlen(local_user)); + packet_put_cstring(local_user); packet_send(); packet_write_wait(); /* The server should respond with success or failure. */ - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) - return; + goto success; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to rhosts auth", type); @@ -1030,10 +1224,12 @@ */ if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) && options.rhosts_rsa_authentication) { - for (i = 0; i < nkeys; i++) { - if (keys[i] != NULL && keys[i]->type == KEY_RSA1 && - try_rhosts_rsa_authentication(local_user, keys[i])) - return; + for (i = 0; i < sensitive->nkeys; i++) { + if (sensitive->keys[i] != NULL && + sensitive->keys[i]->type == KEY_RSA1 && + try_rhosts_rsa_authentication(local_user, + sensitive->keys[i])) + goto success; } } /* Try RSA authentication if the server supports it. */ @@ -1045,20 +1241,20 @@ * it, whereas identity files may require passphrases. */ if (try_agent_authentication()) - return; + goto success; /* Try RSA authentication for each identity. */ for (i = 0; i < options.num_identity_files; i++) if (options.identity_keys[i] != NULL && options.identity_keys[i]->type == KEY_RSA1 && - try_rsa_authentication(options.identity_files[i])) - return; + try_rsa_authentication(i)) + goto success; } /* Try challenge response authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_TIS)) && - options.challenge_reponse_authentication && !options.batch_mode) { - if (try_challenge_reponse_authentication()) - return; + options.challenge_response_authentication && !options.batch_mode) { + if (try_challenge_response_authentication()) + goto success; } /* Try password authentication if the server supports it. */ if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && @@ -1068,9 +1264,43 @@ snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", server_user, host); if (try_password_authentication(prompt)) - return; + goto success; } /* All authentication methods have failed. Exit with an error message. */ fatal("Permission denied."); /* NOTREACHED */ + + success: +#ifdef KRB5 + /* Try Kerberos v5 TGT passing. */ + if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && + options.kerberos_tgt_passing && context && auth_context) { + if (options.cipher == SSH_CIPHER_NONE) + log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); + send_krb5_tgt(context, auth_context); + } + if (auth_context) + krb5_auth_con_free(context, auth_context); + if (context) + krb5_free_context(context); +#endif + +#ifdef AFS + /* Try Kerberos v4 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!"); + send_krb4_tgt(); + } + /* 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 */ + + return; /* need statement after label */ } Index: src/crypto/openssh/sshconnect2.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshconnect2.c,v retrieving revision 1.1.1.2.2.5 diff -u -u -r1.1.1.2.2.5 sshconnect2.c --- src/crypto/openssh/sshconnect2.c 28 Sep 2001 01:33:35 -0000 1.1.1.2.2.5 +++ src/crypto/openssh/sshconnect2.c 30 Jun 2002 11:38:02 -0000 @@ -23,30 +23,21 @@ */ #include "includes.h" -RCSID("$FreeBSD: src/crypto/openssh/sshconnect2.c,v 1.1.1.2.2.5 2001/09/28 01:33:35 green Exp $"); -RCSID("$OpenBSD: sshconnect2.c,v 1.72 2001/04/18 23:43:26 markus Exp $"); - -#include -#include -#include -#include +RCSID("$OpenBSD: sshconnect2.c,v 1.105 2002/06/23 03:30:17 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/sshconnect2.c,v 1.8 2002/06/29 11:48:59 des Exp $"); #include "ssh.h" #include "ssh2.h" #include "xmalloc.h" -#include "rsa.h" #include "buffer.h" #include "packet.h" -#include "uidswap.h" #include "compat.h" #include "bufaux.h" #include "cipher.h" #include "kex.h" #include "myproposal.h" -#include "key.h" #include "sshconnect.h" #include "authfile.h" -#include "cli.h" #include "dh.h" #include "authfd.h" #include "log.h" @@ -55,6 +46,8 @@ #include "match.h" #include "dispatch.h" #include "canohost.h" +#include "msg.h" +#include "pathnames.h" /* import */ extern char *client_version_string; @@ -73,11 +66,11 @@ Kex *xxx_kex = NULL; -int -check_host_key_callback(Key *hostkey) +static int +verify_host_key_callback(Key *hostkey) { - check_host_key(xxx_host, xxx_hostaddr, hostkey, - options.user_hostfile2, options.system_hostfile2); + if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) + fatal("Host key verification failed."); return 0; } @@ -113,14 +106,14 @@ myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; } if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = options.hostkeyalgorithms; /* start key exchange */ kex = kex_setup(myproposal); kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; - kex->check_host_key=&check_host_key_callback; + kex->verify_host_key=&verify_host_key_callback; xxx_kex = kex; @@ -148,7 +141,7 @@ typedef int sign_cb_fn( Authctxt *authctxt, Key *key, - u_char **sigp, int *lenp, u_char *data, int datalen); + u_char **sigp, u_int *lenp, u_char *data, u_int datalen); struct Authctxt { const char *server_user; @@ -164,8 +157,9 @@ int last_key_hint; AuthenticationConnection *agent; /* hostbased */ - Key **keys; - int nkeys; + Sensitive *sensitive; + /* kbd-interactive */ + int info_req_seen; }; struct Authmethod { char *name; /* string to compare against server's list */ @@ -174,47 +168,46 @@ int *batch_flag; /* flag in option struct that disables method */ }; -void input_userauth_success(int type, int plen, void *ctxt); -void input_userauth_failure(int type, int plen, void *ctxt); -void input_userauth_banner(int type, int plen, void *ctxt); -void input_userauth_error(int type, int plen, void *ctxt); -void input_userauth_info_req(int type, int plen, void *ctxt); -void input_userauth_pk_ok(int type, int plen, void *ctxt); - -int userauth_none(Authctxt *authctxt); -int userauth_pubkey(Authctxt *authctxt); -int userauth_passwd(Authctxt *authctxt); -int userauth_kbdint(Authctxt *authctxt); -int userauth_hostbased(Authctxt *authctxt); - -void userauth(Authctxt *authctxt, char *authlist); - -int -sign_and_send_pubkey(Authctxt *authctxt, Key *k, - sign_cb_fn *sign_callback); -void clear_auth_state(Authctxt *authctxt); - -Authmethod *authmethod_get(char *authlist); -Authmethod *authmethod_lookup(const char *name); -char *authmethods_get(void); +void input_userauth_success(int, u_int32_t, void *); +void input_userauth_failure(int, u_int32_t, void *); +void input_userauth_banner(int, u_int32_t, void *); +void input_userauth_error(int, u_int32_t, void *); +void input_userauth_info_req(int, u_int32_t, void *); +void input_userauth_pk_ok(int, u_int32_t, void *); +void input_userauth_passwd_changereq(int, u_int32_t, void *); + +int userauth_none(Authctxt *); +int userauth_pubkey(Authctxt *); +int userauth_passwd(Authctxt *); +int userauth_kbdint(Authctxt *); +int userauth_hostbased(Authctxt *); + +void userauth(Authctxt *, char *); + +static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); +static void clear_auth_state(Authctxt *); + +static Authmethod *authmethod_get(char *authlist); +static Authmethod *authmethod_lookup(const char *name); +static char *authmethods_get(void); Authmethod authmethods[] = { + {"hostbased", + userauth_hostbased, + &options.hostbased_authentication, + NULL}, {"publickey", userauth_pubkey, &options.pubkey_authentication, NULL}, - {"password", - userauth_passwd, - &options.password_authentication, - &options.batch_mode}, {"keyboard-interactive", userauth_kbdint, &options.kbd_interactive_authentication, &options.batch_mode}, - {"hostbased", - userauth_hostbased, - &options.hostbased_authentication, - NULL}, + {"password", + userauth_passwd, + &options.password_authentication, + &options.batch_mode}, {"none", userauth_none, NULL, @@ -224,13 +217,12 @@ void ssh_userauth2(const char *local_user, const char *server_user, char *host, - Key **keys, int nkeys) + Sensitive *sensitive) { Authctxt authctxt; int type; - int plen; - if (options.challenge_reponse_authentication) + if (options.challenge_response_authentication) options.kbd_interactive_authentication = 1; debug("send SSH2_MSG_SERVICE_REQUEST"); @@ -238,24 +230,25 @@ packet_put_cstring("ssh-userauth"); packet_send(); packet_write_wait(); - type = packet_read(&plen); + type = packet_read(); if (type != SSH2_MSG_SERVICE_ACCEPT) { fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type); } if (packet_remaining() > 0) { - char *reply = packet_get_string(&plen); + char *reply = packet_get_string(NULL); debug("service_accept: %s", reply); xfree(reply); } else { debug("buggy server: service_accept w/o service"); } - packet_done(); + packet_check_eom(); debug("got SSH2_MSG_SERVICE_ACCEPT"); if (options.preferred_authentications == NULL) options.preferred_authentications = authmethods_get(); /* setup authentication context */ + memset(&authctxt, 0, sizeof(authctxt)); authctxt.agent = ssh_get_authentication_connection(); authctxt.server_user = server_user; authctxt.local_user = local_user; @@ -264,8 +257,8 @@ authctxt.success = 0; authctxt.method = authmethod_lookup("none"); authctxt.authlist = NULL; - authctxt.keys = keys; - authctxt.nkeys = nkeys; + authctxt.sensitive = sensitive; + authctxt.info_req_seen = 0; if (authctxt.method == NULL) fatal("ssh_userauth2: internal error: cannot send userauth none request"); @@ -307,14 +300,16 @@ } } } + void -input_userauth_error(int type, int plen, void *ctxt) +input_userauth_error(int type, u_int32_t seq, void *ctxt) { fatal("input_userauth_error: bad message during authentication: " "type %d", type); } + void -input_userauth_banner(int type, int plen, void *ctxt) +input_userauth_banner(int type, u_int32_t seq, void *ctxt) { char *msg, *lang; debug3("input_userauth_banner"); @@ -324,8 +319,9 @@ xfree(msg); xfree(lang); } + void -input_userauth_success(int type, int plen, void *ctxt) +input_userauth_success(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; if (authctxt == NULL) @@ -335,8 +331,9 @@ clear_auth_state(authctxt); authctxt->success = 1; /* break out */ } + void -input_userauth_failure(int type, int plen, void *ctxt) +input_userauth_failure(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; char *authlist = NULL; @@ -347,7 +344,7 @@ authlist = packet_get_string(NULL); partial = packet_get_char(); - packet_done(); + packet_check_eom(); if (partial != 0) log("Authenticated with partial success."); @@ -357,13 +354,15 @@ userauth(authctxt, authlist); } void -input_userauth_pk_ok(int type, int plen, void *ctxt) +input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Key *key = NULL; Buffer b; - int alen, blen, sent = 0; - char *pkalg, *pkblob, *fp; + int pktype, sent = 0; + u_int alen, blen; + char *pkalg, *fp; + u_char *pkblob; if (authctxt == NULL) fatal("input_userauth_pk_ok: no authentication context"); @@ -379,9 +378,9 @@ pkalg = packet_get_string(&alen); pkblob = packet_get_string(&blen); } - packet_done(); + packet_check_eom(); - debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d", + debug("input_userauth_pk_ok: pkalg %s blen %u lastkey %p hint %d", pkalg, blen, authctxt->last_key, authctxt->last_key_hint); do { @@ -390,7 +389,7 @@ debug("no last key or no sign cb"); break; } - if (key_type_from_name(pkalg) == KEY_UNSPEC) { + if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { debug("unknown pkalg %s", pkalg); break; } @@ -398,6 +397,12 @@ debug("no key from blob. pkalg %s", pkalg); break; } + if (key->type != pktype) { + error("input_userauth_pk_ok: type mismatch " + "for decoded key (received %d, expected %d)", + key->type, pktype); + break; + } fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); debug2("input_userauth_pk_ok: fp %s", fp); xfree(fp); @@ -407,7 +412,7 @@ } sent = sign_and_send_pubkey(authctxt, key, authctxt->last_key_sign); - } while(0); + } while (0); if (key != NULL) key_free(key); @@ -440,13 +445,13 @@ userauth_passwd(Authctxt *authctxt) { static int attempt = 0; - char prompt[80]; + char prompt[150]; char *password; if (attempt++ >= options.number_of_password_prompts) return 0; - if(attempt != 1) + if (attempt != 1) error("Permission denied, please try again."); snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", @@ -457,18 +462,90 @@ packet_put_cstring(authctxt->service); packet_put_cstring(authctxt->method->name); packet_put_char(0); - ssh_put_password(password); + packet_put_cstring(password); memset(password, 0, strlen(password)); xfree(password); - packet_inject_ignore(64); + packet_add_padding(64); packet_send(); + + dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, + &input_userauth_passwd_changereq); + return 1; } - +/* + * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST + */ void +input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) +{ + Authctxt *authctxt = ctxt; + char *info, *lang, *password = NULL, *retype = NULL; + char prompt[150]; + + debug2("input_userauth_passwd_changereq"); + + if (authctxt == NULL) + fatal("input_userauth_passwd_changereq: " + "no authentication context"); + + info = packet_get_string(NULL); + lang = packet_get_string(NULL); + if (strlen(info) > 0) + log("%s", info); + xfree(info); + xfree(lang); + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_put_char(1); /* additional info */ + snprintf(prompt, sizeof(prompt), + "Enter %.30s@%.128s's old password: ", + authctxt->server_user, authctxt->host); + password = read_passphrase(prompt, 0); + packet_put_cstring(password); + memset(password, 0, strlen(password)); + xfree(password); + password = NULL; + while (password == NULL) { + snprintf(prompt, sizeof(prompt), + "Enter %.30s@%.128s's new password: ", + authctxt->server_user, authctxt->host); + password = read_passphrase(prompt, RP_ALLOW_EOF); + if (password == NULL) { + /* bail out */ + return; + } + snprintf(prompt, sizeof(prompt), + "Retype %.30s@%.128s's new password: ", + authctxt->server_user, authctxt->host); + retype = read_passphrase(prompt, 0); + if (strcmp(password, retype) != 0) { + memset(password, 0, strlen(password)); + xfree(password); + log("Mismatch; try again, EOF to quit."); + password = NULL; + } + memset(retype, 0, strlen(retype)); + xfree(retype); + } + packet_put_cstring(password); + memset(password, 0, strlen(password)); + xfree(password); + packet_add_padding(64); + packet_send(); + + dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, + &input_userauth_passwd_changereq); +} + +static void clear_auth_state(Authctxt *authctxt) { /* XXX clear authentication state */ + dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL); + if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) { debug3("clear_auth_state: key_free %p", authctxt->last_key); key_free(authctxt->last_key); @@ -478,12 +555,12 @@ authctxt->last_key_sign = NULL; } -int +static int sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) { Buffer b; u_char *blob, *signature; - int bloblen, slen; + u_int bloblen, slen; int skip = 0; int ret = -1; int have_sig = 1; @@ -563,12 +640,12 @@ return 1; } -int +static int send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback, int hint) { u_char *blob; - int bloblen, have_sig = 0; + u_int bloblen, have_sig = 0; debug3("send_pubkey_test"); @@ -596,7 +673,7 @@ return 1; } -Key * +static Key * load_identity_file(char *filename) { Key *private; @@ -613,7 +690,7 @@ if (options.batch_mode) return NULL; snprintf(prompt, sizeof prompt, - "Enter passphrase for key '%.100s': ", filename); + "Enter passphrase for key '%.100s': ", filename); for (i = 0; i < options.number_of_password_prompts; i++) { passphrase = read_passphrase(prompt, 0); if (strcmp(passphrase, "") != 0) { @@ -634,9 +711,9 @@ return private; } -int -identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +static int +identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { Key *private; int idx, ret; @@ -644,6 +721,11 @@ idx = authctxt->last_key_hint; if (idx < 0) return -1; + + /* private key is stored in external hardware */ + if (options.identity_keys[idx]->flags & KEY_FLAG_EXT) + return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen); + private = load_identity_file(options.identity_files[idx]); if (private == NULL) return -1; @@ -652,19 +734,21 @@ return ret; } -int agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +static int +agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen); } -int key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +static int +key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { return key_sign(key, sigp, lenp, data, datalen); } -int +static int userauth_pubkey_agent(Authctxt *authctxt) { static int called = 0; @@ -703,7 +787,7 @@ if (authctxt->agent != NULL) { do { sent = userauth_pubkey_agent(authctxt); - } while(!sent && authctxt->agent->howmany > 0); + } while (!sent && authctxt->agent->howmany > 0); } while (!sent && idx < options.num_identity_files) { key = options.identity_keys[idx]; @@ -736,6 +820,12 @@ if (attempt++ >= options.number_of_password_prompts) return 0; + /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ + if (attempt > 1 && !authctxt->info_req_seen) { + debug3("userauth_kbdint: disable: no info_req_seen"); + dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); + return 0; + } debug2("userauth_kbdint"); packet_start(SSH2_MSG_USERAUTH_REQUEST); @@ -755,7 +845,7 @@ * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ void -input_userauth_info_req(int type, int plen, void *ctxt) +input_userauth_info_req(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; char *name, *inst, *lang, *prompt, *response; @@ -767,13 +857,15 @@ if (authctxt == NULL) fatal("input_userauth_info_req: no authentication context"); + authctxt->info_req_seen = 1; + name = packet_get_string(NULL); inst = packet_get_string(NULL); lang = packet_get_string(NULL); if (strlen(name) > 0) - cli_mesg(name); + log("%s", name); if (strlen(inst) > 0) - cli_mesg(inst); + log("%s", inst); xfree(name); xfree(inst); xfree(lang); @@ -788,31 +880,104 @@ packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); packet_put_int(num_prompts); + debug2("input_userauth_info_req: num_prompts %d", num_prompts); for (i = 0; i < num_prompts; i++) { prompt = packet_get_string(NULL); echo = packet_get_char(); - response = cli_prompt(prompt, echo); + response = read_passphrase(prompt, echo ? RP_ECHO : 0); - ssh_put_password(response); + packet_put_cstring(response); memset(response, 0, strlen(response)); xfree(response); xfree(prompt); } - packet_done(); /* done with parsing incoming message. */ + packet_check_eom(); /* done with parsing incoming message. */ - packet_inject_ignore(64); + packet_add_padding(64); packet_send(); } -/* - * this will be move to an external program (ssh-keysign) ASAP. ssh-keysign - * will be setuid-root and the sbit can be removed from /usr/bin/ssh. - */ +static int +ssh_keysign(Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) +{ + Buffer b; + struct stat st; + pid_t pid; + int to[2], from[2], status, version = 2; + + debug("ssh_keysign called"); + + if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { + error("ssh_keysign: no installed: %s", strerror(errno)); + return -1; + } + if (fflush(stdout) != 0) + error("ssh_keysign: fflush: %s", strerror(errno)); + if (pipe(to) < 0) { + error("ssh_keysign: pipe: %s", strerror(errno)); + return -1; + } + if (pipe(from) < 0) { + error("ssh_keysign: pipe: %s", strerror(errno)); + return -1; + } + if ((pid = fork()) < 0) { + error("ssh_keysign: fork: %s", strerror(errno)); + return -1; + } + if (pid == 0) { + seteuid(getuid()); + setuid(getuid()); + close(from[0]); + if (dup2(from[1], STDOUT_FILENO) < 0) + fatal("ssh_keysign: dup2: %s", strerror(errno)); + close(to[1]); + if (dup2(to[0], STDIN_FILENO) < 0) + fatal("ssh_keysign: dup2: %s", strerror(errno)); + close(from[1]); + close(to[0]); + execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); + fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, + strerror(errno)); + } + close(from[1]); + close(to[0]); + + buffer_init(&b); + buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ + buffer_put_string(&b, data, datalen); + msg_send(to[1], version, &b); + + if (msg_recv(from[0], &b) < 0) { + error("ssh_keysign: no reply"); + buffer_clear(&b); + return -1; + } + close(from[0]); + close(to[1]); + + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) + break; + + if (buffer_get_char(&b) != version) { + error("ssh_keysign: bad version"); + buffer_clear(&b); + return -1; + } + *sigp = buffer_get_string(&b, lenp); + buffer_clear(&b); + + return 0; +} + int userauth_hostbased(Authctxt *authctxt) { Key *private = NULL; + Sensitive *sensitive = authctxt->sensitive; Buffer b; u_char *signature, *blob; char *chost, *pkalg, *p; @@ -820,35 +985,37 @@ u_int blen, slen; int ok, i, len, found = 0; - p = get_local_name(packet_get_connection_in()); - if (p == NULL) { - error("userauth_hostbased: cannot get local ipaddr/name"); - return 0; - } - len = strlen(p) + 2; - chost = xmalloc(len); - strlcpy(chost, p, len); - strlcat(chost, ".", len); - debug2("userauth_hostbased: chost %s", chost); /* check for a useful key */ - for (i = 0; i < authctxt->nkeys; i++) { - private = authctxt->keys[i]; + for (i = 0; i < sensitive->nkeys; i++) { + private = sensitive->keys[i]; if (private && private->type != KEY_RSA1) { found = 1; /* we take and free the key */ - authctxt->keys[i] = NULL; + sensitive->keys[i] = NULL; break; } } if (!found) { - xfree(chost); + debug("userauth_hostbased: no more client hostkeys"); return 0; } if (key_to_blob(private, &blob, &blen) == 0) { key_free(private); - xfree(chost); return 0; } + /* figure out a name for the client host */ + p = get_local_name(packet_get_connection_in()); + if (p == NULL) { + error("userauth_hostbased: cannot get local ipaddr/name"); + key_free(private); + return 0; + } + len = strlen(p) + 2; + chost = xmalloc(len); + strlcpy(chost, p, len); + strlcat(chost, ".", len); + debug2("userauth_hostbased: chost %s", chost); + service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; pkalg = xstrdup(key_ssh_name(private)); @@ -866,8 +1033,12 @@ #ifdef DEBUG_PK buffer_dump(&b); #endif - debug2("xxx: chost %s", chost); - ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); + if (sensitive->external_keysign) + ok = ssh_keysign(private, &signature, &slen, + buffer_ptr(&b), buffer_len(&b)); + else + ok = key_sign(private, &signature, &slen, + buffer_ptr(&b), buffer_len(&b)); key_free(private); buffer_free(&b); if (ok != 0) { @@ -900,7 +1071,7 @@ * given auth method name, if configurable options permit this method fill * in auth_ident field and return true, otherwise return false. */ -int +static int authmethod_is_enabled(Authmethod *method) { if (method == NULL) @@ -914,7 +1085,7 @@ return 1; } -Authmethod * +static Authmethod * authmethod_lookup(const char *name) { Authmethod *method = NULL; @@ -930,17 +1101,18 @@ static Authmethod *current = NULL; static char *supported = NULL; static char *preferred = NULL; + /* * Given the authentication method list sent by the server, return the * next method we should try. If the server initially sends a nil list, * use a built-in default list. */ -Authmethod * +static Authmethod * authmethod_get(char *authlist) { char *name = NULL; - int next; + u_int next; /* Use a suitable default if we're passed a nil list. */ if (authlist == NULL || strlen(authlist) == 0) @@ -975,21 +1147,23 @@ } } - -#define DELIM "," -char * +static char * authmethods_get(void) { Authmethod *method = NULL; - char buf[1024]; + Buffer b; + char *list; - buf[0] = '\0'; + buffer_init(&b); for (method = authmethods; method->name != NULL; method++) { if (authmethod_is_enabled(method)) { - if (buf[0] != '\0') - strlcat(buf, DELIM, sizeof buf); - strlcat(buf, method->name, sizeof buf); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, method->name, strlen(method->name)); } } - return xstrdup(buf); + buffer_append(&b, "\0", 1); + list = xstrdup(buffer_ptr(&b)); + buffer_free(&b); + return list; } Index: src/crypto/openssh/sshd.8 =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshd.8,v retrieving revision 1.5.2.7 diff -u -u -r1.5.2.7 sshd.8 --- src/crypto/openssh/sshd.8 28 Sep 2001 01:33:35 -0000 1.5.2.7 +++ src/crypto/openssh/sshd.8 30 Jun 2002 11:38:02 -0000 @@ -34,9 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.120 2001/04/22 23:58:36 markus Exp $ -.\" $FreeBSD: src/crypto/openssh/sshd.8,v 1.5.2.7 2001/09/28 01:33:35 green Exp $ -.\" +.\" $OpenBSD: sshd.8,v 1.186 2002/06/22 16:45:29 stevesk Exp $ +.\" $FreeBSD: src/crypto/openssh/sshd.8,v 1.23 2002/06/29 11:48:59 des Exp $ .Dd September 25, 1999 .Dt SSHD 8 .Os @@ -45,15 +44,15 @@ .Nd OpenSSH SSH daemon .Sh SYNOPSIS .Nm sshd -.Op Fl deiqD46 +.Op Fl deiqtD46 .Op Fl b Ar bits .Op Fl f Ar config_file .Op Fl g Ar login_grace_time .Op Fl h Ar host_key_file .Op Fl k Ar key_gen_time +.Op Fl o Ar option .Op Fl p Ar port .Op Fl u Ar len -.Op Fl V Ar client_protocol_id .Sh DESCRIPTION .Nm (SSH Daemon) is the daemon program for @@ -66,8 +65,8 @@ .Pp .Nm is the daemon that listens for connections from clients. -It is normally started at boot from -.Pa /etc/rc.network . +It is normally started at boot from +.Pa /etc/rc.d/sshd . It forks a new daemon for each incoming connection. The forked daemons handle @@ -118,21 +117,20 @@ because it is fundamentally insecure, but can be enabled in the server configuration file if desired. System security is not improved unless -.Xr rshd 8 , -.Xr rlogind 8 , -.Xr rexecd 8 , +.Nm rshd , +.Nm rlogind , and -.Xr rexd 8 +.Xr rexecd are disabled (thus completely disabling -.Xr rlogin 1 +.Xr rlogin and -.Xr rsh 1 +.Xr rsh into the machine). .Pp .Ss SSH protocol version 2 .Pp Version 2 works similarly: -Each host has a host-specific DSA key used to identify the host. +Each host has a host-specific key (RSA or DSA) used to identify the host. However, when the daemon starts, it does not generate a server key. Forward security is provided through a Diffie-Hellman key agreement. This key agreement results in a shared session key. @@ -178,7 +176,7 @@ .Nm rereads its configuration file when it receives a hangup signal, .Dv SIGHUP , -by executing itself with the name it was started as, ie. +by executing itself with the name it was started as, i.e., .Pa /usr/sbin/sshd . .Pp The options are as follows: @@ -186,7 +184,6 @@ .It Fl b Ar bits Specifies the number of bits in the ephemeral protocol version 1 server key (default 768). -.Pp .It Fl d Debug mode. The server sends verbose debug output to the system @@ -212,12 +209,18 @@ this many seconds, the server disconnects and exits. A value of zero indicates no limit. .It Fl h Ar host_key_file -Specifies the file from which the host key is read (default -.Pa /etc/ssh/ssh_host_key ) . +Specifies a file from which a host key is read. This option must be given if .Nm is not run as root (as the normal -host file is normally not readable by anyone but root). +host key files are normally not readable by anyone but root). +The default is +.Pa /etc/ssh/ssh_host_key +for protocol version 1, and +.Pa /etc/ssh/ssh_host_rsa_key +and +.Pa /etc/ssh/ssh_host_dsa_key +for protocol version 2. It is possible to have multiple host key files for the different protocol versions and host key algorithms. .It Fl i @@ -242,14 +245,27 @@ communications even if the machine is cracked into or physically seized. A value of zero indicates that the key will never be regenerated. +.It Fl o Ar option +Can be used to give options in the format used in the configuration file. +This is useful for specifying options for which there is no separate +command-line flag. .It Fl p Ar port Specifies the port on which the server listens for connections (default 22). +Multiple port options are permitted. +Ports specified in the configuration file are ignored when a +command-line port is specified. .It Fl q Quiet mode. Nothing is sent to the system log. Normally the beginning, authentication, and termination of each connection is logged. +.It Fl t +Test mode. +Only check the validity of the configuration file and sanity of the keys. +This is useful for updating +.Nm +reliably as configuration options may change. .It Fl u Ar len This option is used to specify the size of the field in the @@ -266,6 +282,23 @@ should be put into the .Pa utmp file. +.Fl u0 +is also be used to prevent +.Nm +from making DNS requests unless the authentication +mechanism or configuration requires it. +Authentication mechanisms that may require DNS include +.Cm RhostsAuthentication , +.Cm RhostsRSAAuthentication , +.Cm HostbasedAuthentication +and using a +.Cm from="pattern-list" +option in a key file. +Configuration options that require DNS include using a +USER@HOST pattern in +.Cm AllowUsers +or +.Cm DenyUsers . .It Fl D When this option is specified .Nm @@ -288,524 +321,8 @@ (or the file specified with .Fl f on the command line). -The file contains keyword-value pairs, one per line. -Lines starting with -.Ql # -and empty lines are interpreted as comments. -.Pp -The following keywords are possible. -.Bl -tag -width Ds -.It Cm AFSTokenPassing -Specifies whether an AFS token may be forwarded to the server. -Default is -.Dq yes . -.It Cm AllowGroups -This keyword can be followed by a list of group names, separated -by spaces. -If specified, login is allowed only for users whose primary -group or supplementary group list matches one of the patterns. -.Ql \&* -and -.Ql ? -can be used as -wildcards in the patterns. -Only group names are valid; a numerical group ID isn't recognized. -By default login is allowed regardless of the group list. -.Pp -.It Cm AllowTcpForwarding -Specifies whether TCP forwarding is permitted. -The default is -.Dq yes . -Note that disabling TCP forwarding does not improve security unless -users are also denied shell access, as they can always install their -own forwarders. -.Pp -.It Cm AllowUsers -This keyword can be followed by a list of user names, separated -by spaces. -If specified, login is allowed only for users names that -match one of the patterns. -.Ql \&* -and -.Ql ? -can be used as -wildcards in the patterns. -Only user names are valid; a numerical user ID isn't recognized. -By default login is allowed regardless of the user name. -.Pp -.It Cm Banner -In some jurisdictions, sending a warning message before authentication -may be relevant for getting legal protection. -The contents of the specified file are sent to the remote user before -authentication is allowed. -This option is only available for protocol version 2. -.Pp -.It Cm ChallengeResponseAuthentication -Specifies whether -challenge response -authentication is allowed. -Currently there is only support for -.Xr skey 1 -authentication. -The default is -.Dq yes . -.It Cm Ciphers -Specifies the ciphers allowed for protocol version 2. -Multiple ciphers must be comma-separated. -The default is -.Dq aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour. -.It Cm CheckMail -Specifies whether -.Nm -should check for new mail for interactive logins. -The default is -.Dq yes . -.It Cm ClientAliveInterval -Sets a timeout interval in seconds after which if no data has been received -from the client, -.Nm -will send a message through the encrypted -channel to request a response from the client. -The default -is 0, indicating that these messages will not be sent to the client. -This option applies to protocol version 2 only. -.It Cm ClientAliveCountMax -Sets the number of client alive messages (see above) which may be -sent without -.Nm -receiving any messages back from the client. If this threshold is -reached while client alive messages are being sent, -.Nm -will disconnect the client, terminating the session. It is important -to note that the use of client alive messages is very different from -.Cm Keepalive -(below). The client alive messages are sent through the -encrypted channel and therefore will not be spoofable. The TCP keepalive -option enabled by -.Cm Keepalive -is spoofable. You want to use the client -alive mechanism when you are basing something important on -clients having an active connection to the server. -.Pp -The default value is 3. If you set -.Cm ClientAliveInterval -(above) to 15, and leave this value at the default, unresponsive ssh clients -will be disconnected after approximately 45 seconds. -.It Cm DenyGroups -This keyword can be followed by a number of group names, separated -by spaces. -Users whose primary group or supplementary group list matches -one of the patterns aren't allowed to log in. -.Ql \&* -and -.Ql ? -can be used as -wildcards in the patterns. -Only group names are valid; a numerical group ID isn't recognized. -By default login is allowed regardless of the group list. -.Pp -.It Cm DenyUsers -This keyword can be followed by a number of user names, separated -by spaces. -Login is disallowed for user names that match one of the patterns. -.Ql \&* -and -.Ql ? -can be used as wildcards in the patterns. -Only user names are valid; a numerical user ID isn't recognized. -By default login is allowed regardless of the user name. -.It Cm GatewayPorts -Specifies whether remote hosts are allowed to connect to ports -forwarded for the client. -The argument must be -.Dq yes -or -.Dq no . -The default is -.Dq no . -.It Cm HostbasedAuthentication -Specifies whether rhosts or /etc/hosts.equiv authentication together -with successful public key client host authentication is allowed -(hostbased authentication). -This option is similar to -.Cm RhostsRSAAuthentication -and applies to protocol version 2 only. -The default is -.Dq no . -.It Cm HostKey -Specifies the file containing the private host keys (default -.Pa /etc/ssh/ssh_host_key ) -used by SSH protocol versions 1 and 2. -Note that -.Nm -will refuse to use a file if it is group/world-accessible. -It is possible to have multiple host key files. -.Dq rsa1 -keys are used for version 1 and -.Dq dsa -or -.Dq rsa -are used for version 2 of the SSH protocol. -.It Cm IgnoreRhosts -Specifies that -.Pa .rhosts -and -.Pa .shosts -files will not be used in -.Cm RhostsAuthentication , -.Cm RhostsRSAAuthentication -or -.Cm HostbasedAuthentication . -.Pp -.Pa /etc/hosts.equiv -and -.Pa /etc/ssh/shosts.equiv -are still used. -The default is -.Dq yes . -.It Cm IgnoreUserKnownHosts -Specifies whether -.Nm -should ignore the user's -.Pa $HOME/.ssh/known_hosts -during -.Cm RhostsRSAAuthentication -or -.Cm HostbasedAuthentication . -The default is -.Dq no . -.It Cm 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 sent, -sessions may hang indefinitely on the server, leaving -.Dq ghost -users and consuming server resources. -.Pp -The default is -.Dq yes -(to send keepalives), and the server will notice -if the network goes down or the client host reboots. -This avoids infinitely hanging sessions. -.Pp -To disable keepalives, the value should be set to -.Dq no -in both the server and the client configuration files. -.It Cm KerberosAuthentication -Specifies whether Kerberos authentication is allowed. -This can be in the form of a Kerberos ticket, or if -.Cm PasswordAuthentication -is yes, the password provided by the user will be validated through -the Kerberos KDC. -To use this option, the server needs a -Kerberos servtab which allows the verification of the KDC's identity. -Default is -.Dq yes . -.It Cm KerberosOrLocalPasswd -If set then if password authentication through Kerberos fails then -the password will be validated via any additional local mechanism -such as -.Pa /etc/passwd . -Default is -.Dq yes . -.It Cm KerberosTgtPassing -Specifies whether a Kerberos TGT may be forwarded to the server. -Default is -.Dq no , -as this only works when the Kerberos KDC is actually an AFS kaserver. -.It Cm KerberosTicketCleanup -Specifies whether to automatically destroy the user's ticket cache -file on logout. -Default is -.Dq yes . -.It Cm KeyRegenerationInterval -In protocol version 1, the ephemeral 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). -.It Cm ListenAddress -Specifies the local addresses -.Nm -should listen on. -The following forms may be used: -.Pp -.Bl -item -offset indent -compact -.It -.Cm ListenAddress -.Sm off -.Ar host No | Ar IPv4_addr No | Ar IPv6_addr -.Sm on -.It -.Cm ListenAddress -.Sm off -.Ar host No | Ar IPv4_addr No : Ar port -.Sm on -.It -.Cm ListenAddress -.Sm off -.Oo -.Ar host No | Ar IPv6_addr Oc : Ar port -.Sm on -.El -.Pp -If -.Ar port -is not specified, -.Nm -will listen on the address and all prior -.Cm Port -options specified. The default is to listen on all local -addresses. Multiple -.Cm ListenAddress -options are permitted. Additionally, any -.Cm Port -options must precede this option for non port qualified addresses. -.It Cm 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 120 (seconds). -.It Cm LogLevel -Gives the verbosity level that is used when logging messages from -.Nm sshd . -The possible values are: -QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG. -The default is INFO. -Logging with level DEBUG violates the privacy of users -and is not recommended. -.It Cm MACs -Specifies the available MAC (message authentication code) algorithms. -The MAC algorithm is used in protocol version 2 -for data integrity protection. -Multiple algorithms must be comma-separated. -The default is -.Pp -.Bd -literal - ``hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripemd160@openssh.com, - hmac-sha1-96,hmac-md5-96'' -.Ed -.It Cm MaxStartups -Specifies the maximum number of concurrent unauthenticated connections to the -.Nm -daemon. -Additional connections will be dropped until authentication succeeds or the -.Cm LoginGraceTime -expires for a connection. -The default is 10. -.Pp -Alternatively, random early drop can be enabled by specifying -the three colon separated values -.Dq start:rate:full -(e.g., "10:30:60"). -.Nm -will refuse connection attempts with a probability of -.Dq rate/100 -(30%) -if there are currently -.Dq start -(10) -unauthenticated connections. -The probability increases linearly and all connection attempts -are refused if the number of unauthenticated connections reaches -.Dq full -(60). -.It Cm PasswordAuthentication -Specifies whether password authentication is allowed. -The default is -.Dq yes . -.It Cm PermitEmptyPasswords -When password authentication is allowed, it specifies whether the -server allows login to accounts with empty password strings. -The default is -.Dq no . -.It Cm PermitRootLogin -Specifies whether root can login using -.Xr ssh 1 . -The argument must be -.Dq yes , -.Dq without-password , -.Dq forced-commands-only -or -.Dq no . -The default is -.Dq no . -.Pp -If this option is set to -.Dq without-password -password authentication is disabled for root. -.Pp -If this option is set to -.Dq forced-commands-only -root login with public key authentication will be allowed, -but only if the -.Ar command -option has been specified -(which may be useful for taking remote backups even if root login is -normally not allowed). All other authentication methods are disabled -for root. -.Pp -If this option is set to -.Dq no -root is not allowed to login. -.It Cm PidFile -Specifies the file that contains the process identifier of the -.Nm -daemon. -The default is -.Pa /var/run/sshd.pid . -.It Cm Port -Specifies the port number that -.Nm -listens on. -The default is 22. -Multiple options of this type are permitted. -See also -.Cm ListenAddress . -.It Cm PrintLastLog -Specifies whether -.Nm -should print the date and time when the user last logged in. -The default is -.Dq yes . -.It Cm PrintMotd -Specifies whether -.Nm -should print -.Pa /etc/motd -when a user logs in interactively. -(On some systems it is also printed by the shell, -.Pa /etc/profile , -or equivalent.) -The default is -.Dq yes . -.It Cm Protocol -Specifies the protocol versions -.Nm -should support. -The possible values are -.Dq 1 -and -.Dq 2 . -Multiple versions must be comma-separated. -The default is -.Dq 2,1 . -.It Cm PubkeyAuthentication -Specifies whether public key authentication is allowed. -The default is -.Dq yes . -Note that this option applies to protocol version 2 only. -.It Cm ReverseMappingCheck -Specifies whether -.Nm -should try to verify the remote host name and check that -the resolved host name for the remote IP address maps back to the -very same IP address. -The default is -.Dq no . -.It Cm RhostsAuthentication -Specifies whether authentication using rhosts or -.Pa /etc/hosts.equiv -files is sufficient. -Normally, this method should not be permitted because it is insecure. -.Cm RhostsRSAAuthentication -should be used -instead, because it performs RSA-based host authentication in addition -to normal rhosts or -.Pa /etc/hosts.equiv -authentication. -The default is -.Dq no . -This option applies to protocol version 1 only. -.It Cm RhostsRSAAuthentication -Specifies whether rhosts or -.Pa /etc/hosts.equiv -authentication together -with successful RSA host authentication is allowed. -The default is -.Dq no . -This option applies to protocol version 1 only. -.It Cm RSAAuthentication -Specifies whether pure RSA authentication is allowed. -The default is -.Dq yes . -This option applies to protocol version 1 only. -.It Cm ServerKeyBits -Defines the number of bits in the ephemeral protocol version 1 server key. -The minimum value is 512, and the default is 768. -.It Cm SkeyAuthentication -Specifies whether -.Xr skey 1 -authentication is allowed. -The default is -.Dq yes . -Note that OPIE authentication is enabled only if -.Cm PasswordAuthentication -is allowed, too. -.It Cm StrictModes -Specifies whether -.Nm -should check file modes and ownership of the -user's files and home directory before accepting login. -This is normally desirable because novices sometimes accidentally leave their -directory or files world-writable. -The default is -.Dq yes . -.It Cm Subsystem -Configures an external subsystem (e.g., file transfer daemon). -Arguments should be a subsystem name and a command to execute upon subsystem -request. -The command -.Xr sftp-server 8 -implements the -.Dq sftp -file transfer subsystem. -By default no subsystems are defined. -Note that this option applies to protocol version 2 only. -.It Cm SyslogFacility -Gives the facility code that is used when logging messages from -.Nm sshd . -The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, -LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. -The default is AUTH. -.It Cm UseLogin -Specifies whether -.Xr login 1 -is used for interactive login sessions. -Note that -.Xr login 1 -is never used for remote command execution. -The default is -.Dq no . -.It Cm X11DisplayOffset -Specifies the first display number available for -.Nm sshd Ns 's -X11 forwarding. -This prevents -.Nm -from interfering with real X11 servers. -The default is 10. -.It Cm X11Forwarding -Specifies whether X11 forwarding is permitted. -The default is -.Dq no . -Note that disabling X11 forwarding does not improve security in any -way, as users can always install their own forwarders. -.It Cm XAuthLocation -Specifies the location of the -.Xr xauth 1 -program. -The default is -.Pa /usr/X11R6/bin/xauth . -.El +The file format and configuration options are described in +.Xr sshd_config 5 . .Sh LOGIN PROCESS When a user successfully logs in, .Nm @@ -854,15 +371,13 @@ Runs user's shell or command. .El .Sh AUTHORIZED_KEYS FILE FORMAT -The .Pa $HOME/.ssh/authorized_keys -file lists the RSA keys that are +is the default file that lists the public keys that are permitted for RSA authentication in protocol version 1 -Similarly, the -.Pa $HOME/.ssh/authorized_keys2 -file lists the DSA and RSA keys that are -permitted for public key authentication (PubkeyAuthentication) +and for public key authentication (PubkeyAuthentication) in protocol version 2. +.Cm AuthorizedKeysFile +may be used to specify an alternative file. .Pp Each line of the file contains one key (empty lines and lines starting with a @@ -894,10 +409,15 @@ .Pa id_rsa.pub file and edit it. .Pp +.Nm +enforces a minimum RSA key modulus size for protocol 1 +and protocol 2 keys of 768 bits. +.Pp The options (if present) consist of comma-separated option specifications. No spaces are permitted, except within double quotes. -The following option specifications are supported: +The following option specifications are supported (note +that option keywords are case-insensitive): .Bl -tag -width Ds .It Cm from="pattern-list" Specifies that in addition to RSA authentication, the canonical name @@ -923,10 +443,10 @@ 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; +The command is run on a pty if the client requests a pty; otherwise it is run without a tty. -Note that if you want a 8-bit clean channel, -you must not request a pty or should specify +If a 8-bit clean channel is required, +one must not request a pty or should specify .Cm no-pty . A quote may be included in the command by quoting it with a backslash. This option might be useful @@ -934,12 +454,16 @@ An example might be a key that permits remote backups but nothing else. Note that the client may specify TCP/IP and/or X11 forwarding unless they are explicitly prohibited. +Note that this option applies to shell, command or subsystem execution. .It Cm environment="NAME=value" 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. +This option is automatically disabled if +.Cm UseLogin +is enabled. .It Cm 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. @@ -955,13 +479,16 @@ .It Cm no-pty Prevents tty allocation (a request to allocate a pty will fail). .It Cm permitopen="host:port" -Limit local +Limit local .Li ``ssh -L'' port forwarding such that it may only connect to the specified host and -port. Multiple +port. +IPv6 addresses can be specified with an alternative syntax: +.Ar host/port . +Multiple .Cm permitopen -options may be applied separated by commas. No pattern matching is -performed on the specified hostnames, they must be literal domains or +options may be applied separated by commas. No pattern matching is +performed on the specified hostnames, they must be literal domains or addresses. .El .Ss Examples @@ -974,11 +501,9 @@ permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23.\|.\|.\|2323 .Sh SSH_KNOWN_HOSTS FILE FORMAT The -.Pa /etc/ssh/ssh_known_hosts , -.Pa /etc/ssh/ssh_known_hosts2 , -.Pa $HOME/.ssh/known_hosts , +.Pa /etc/ssh/ssh_known_hosts and -.Pa $HOME/.ssh/known_hosts2 +.Pa $HOME/.ssh/known_hosts files contain host public keys for all known hosts. The global file should be prepared by the administrator (optional), and the per-user file is @@ -1035,8 +560,8 @@ .It Pa /etc/ssh/sshd_config Contains configuration data for .Nm sshd . -This file should be writable by root only, but it is recommended -(though not necessary) that it be world-readable. +The file format and configuration options are described in +.Xr sshd_config 5 . .It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys. These files should only be owned by root, readable only by root, and not @@ -1054,27 +579,23 @@ the user so their contents can be copied to known hosts files. These files are created using .Xr ssh-keygen 1 . -.It Pa /etc/primes +.It Pa /etc/ssh/moduli Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange". +.It Pa /var/empty +.Xr chroot 2 +directory used by +.Nm +during privilege separation in the pre-authentication phase. +The directory should not contain any files and must be owned by root +and not group or world-writable. .It Pa /var/run/sshd.pid Contains the process ID of the .Nm listening for connections (if there are several daemons running -concurrently for different ports, this contains the pid of the one +concurrently for different ports, this contains the process ID of the one started last). The content of this file is not sensitive; it can be world-readable. .It Pa $HOME/.ssh/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. -Users will place the contents of their -.Pa identity.pub -files into this file, as described in -.Xr ssh-keygen 1 . -.It Pa $HOME/.ssh/authorized_keys2 Lists the public keys (RSA or DSA) 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 @@ -1082,6 +603,7 @@ It is recommended that it not be accessible by others. The format of this file is described above. Users will place the contents of their +.Pa identity.pub , .Pa id_dsa.pub and/or .Pa id_rsa.pub @@ -1089,7 +611,8 @@ .Xr ssh-keygen 1 . .It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts" These files are consulted when using rhosts with RSA host -authentication to check the public key of the host. +authentication or protocol version 2 hostbased 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 it is connecting to the correct remote host. @@ -1098,17 +621,6 @@ should be world-readable, and .Pa $HOME/.ssh/known_hosts can but need not be world-readable. -.It Pa "/etc/ssh_known_hosts2" and "$HOME/.ssh/known_hosts2" -These files are consulted when using protocol version 2 hostbased -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 it is connecting to the correct remote host. -These files should be writable only by root/the owner. -.Pa /etc/ssh_known_hosts2 -should be world-readable, and -.Pa $HOME/.ssh/known_hosts2 -can but need not be world-readable. .It Pa /etc/nologin If this file exists, .Nm @@ -1117,10 +629,9 @@ are displayed to anyone trying to log in, and non-root connections are refused. The file should be world-readable. -.It Pa /etc/hosts.allow -If compiled with -.Sy LIBWRAP -support, tcp-wrappers access controls may be defined here as described in +.It Pa /etc/hosts.allow, /etc/hosts.deny +Access controls that should be enforced by tcp-wrappers are defined here. +Further details are described in .Xr hosts_access 5 . .It Pa $HOME/.rhosts This file contains host-username pairs, separated by a space, one per @@ -1195,13 +706,17 @@ .Pa /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 +It must not produce any output on stdout; stderr must be used +instead. +If X11 forwarding is in use, it will receive the "proto cookie" pair in +its standard input (and .Ev DISPLAY -in environment). -This must call +in its environment). +The script must call .Xr xauth 1 -in that case. +because +.Nm +will not run xauth automatically to add X11 cookies. .Pp The primary purpose of this file is to run any initialization routines which may be needed before the user's home directory becomes @@ -1209,18 +724,23 @@ .Pp This file will probably contain some initialization code followed by something similar to: -.Bd -literal -offset indent -if [ -n "$DISPLAY" ] && read proto cookie; then - echo add "$DISPLAY" "$proto" "$cookie" | xauth -q - +.Bd -literal +if read proto cookie && [ -n "$DISPLAY" ]; then + if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then + # X11UseLocalhost=yes + xauth add unix:`echo $DISPLAY | + cut -c11-` $proto $cookie + else + # X11UseLocalhost=no + xauth add $DISPLAY $proto $cookie + fi fi .Ed .Pp If this file does not exist, .Pa /etc/ssh/sshrc is run, and if that -does not exist either, -.Xr xauth 1 -is used to store the cookie. +does not exist either, xauth is used to add the cookie. .Pp This file should be writable only by the user, and need not be readable by anyone else. @@ -1240,16 +760,19 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Niels Provos and Markus Friedl contributed support +for privilege separation. .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , -.Xr sftp-server 8 , .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 , -.Xr rlogin 1 , -.Xr rsh 1 +.Xr login.conf 5 , +.Xr moduli 5 , +.Xr sshd_config 5 , +.Xr sftp-server 8 .Rs .%A T. Ylonen .%A T. Kivinen @@ -1257,8 +780,8 @@ .%A T. Rinne .%A S. Lehtinen .%T "SSH Protocol Architecture" -.%N draft-ietf-secsh-architecture-07.txt -.%D January 2001 +.%N draft-ietf-secsh-architecture-12.txt +.%D January 2002 .%O work in progress material .Re .Rs @@ -1266,7 +789,7 @@ .%A N. Provos .%A W. A. Simpson .%T "Diffie-Hellman Group Exchange for the SSH Transport Layer Protocol" -.%N draft-ietf-secsh-dh-group-exchange-00.txt -.%D January 2001 +.%N draft-ietf-secsh-dh-group-exchange-02.txt +.%D January 2002 .%O work in progress material .Re Index: src/crypto/openssh/sshd.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshd.c,v retrieving revision 1.6.2.9 diff -u -u -r1.6.2.9 sshd.c --- src/crypto/openssh/sshd.c 28 Sep 2001 01:33:35 -0000 1.6.2.9 +++ src/crypto/openssh/sshd.c 30 Jun 2002 11:38:02 -0000 @@ -15,8 +15,10 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation: + * Privilege Separation: * - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2002 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,12 +42,17 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.195 2001/04/15 16:58:03 markus Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/sshd.c,v 1.6.2.9 2001/09/28 01:33:35 green Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.251 2002/06/25 18:51:04 markus Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/sshd.c,v 1.30 2002/06/29 11:48:59 des Exp $"); #include #include -#include +#include +#include +#ifdef HAVE_SECUREWARE +#include +#include +#endif #include "ssh.h" #include "ssh1.h" @@ -60,9 +67,6 @@ #include "uidswap.h" #include "compat.h" #include "buffer.h" -#include -#include - #include "cipher.h" #include "kex.h" #include "key.h" @@ -75,6 +79,12 @@ #include "auth.h" #include "misc.h" #include "dispatch.h" +#include "channels.h" +#include "session.h" +#include "monitor_mm.h" +#include "monitor.h" +#include "monitor_wrap.h" +#include "monitor_fdpass.h" #ifdef LIBWRAP #include @@ -87,11 +97,11 @@ #define O_NOCTTY 0 #endif -#ifdef KRB5 -#include -#endif /* KRB5 */ - +#ifdef HAVE___PROGNAME extern char *__progname; +#else +char *__progname; +#endif /* Server configuration options. */ ServerOptions options; @@ -103,7 +113,11 @@ * Flag indicating whether IPv4 or IPv6. This can be set on the command line. * Default value is AF_UNSPEC means both IPv4 and IPv6. */ +#ifdef IPV4_DEFAULT +int IPv4or6 = AF_INET; +#else int IPv4or6 = AF_UNSPEC; +#endif /* * Debug mode flag. This can be set on the command line. If debug @@ -113,6 +127,9 @@ */ int debug_flag = 0; +/* Flag indicating that the daemon should only test the configuration and keys. */ +int test_flag = 0; + /* Flag indicating that the daemon is being started from inetd. */ int inetd_flag = 0; @@ -124,6 +141,7 @@ /* Saved arguments to main(). */ char **saved_argv; +int saved_argc; /* * The sockets that the server is listening; this is used in the SIGHUP @@ -164,10 +182,11 @@ * Flag indicating whether the RSA server key needs to be regenerated. * Is set in the SIGALRM handler and cleared when the key is regenerated. */ -int key_do_regen = 0; +static volatile sig_atomic_t key_do_regen = 0; -/* This is set to true when SIGHUP is received. */ -int received_sighup = 0; +/* This is set to true when a signal is received. */ +static volatile sig_atomic_t received_sighup = 0; +static volatile sig_atomic_t received_sigterm = 0; /* session identifier, used by RSA-auth */ u_char session_id[16]; @@ -179,76 +198,98 @@ /* record remote hostname or ip */ u_int utmp_len = MAXHOSTNAMELEN; +/* options.max_startup sized array of fd ints */ +int *startup_pipes = NULL; +int startup_pipe; /* in child */ + +/* variables used for privilege separation */ +extern struct monitor *pmonitor; +extern int use_privsep; + /* Prototypes for various functions defined later in this file. */ -void do_ssh1_kex(void); -void do_ssh2_kex(void); +void destroy_sensitive_data(void); +void demote_sensitive_data(void); -void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *); -void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *); +static void do_ssh1_kex(void); +static void do_ssh2_kex(void); /* * Close all listening sockets */ -void +static void close_listen_socks(void) { int i; + for (i = 0; i < num_listen_socks; i++) close(listen_socks[i]); num_listen_socks = -1; } +static void +close_startup_pipes(void) +{ + int i; + + if (startup_pipes) + for (i = 0; i < options.max_startups; i++) + if (startup_pipes[i] != -1) + close(startup_pipes[i]); +} + /* * 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). */ -void +static void sighup_handler(int sig) { + int save_errno = errno; + received_sighup = 1; signal(SIGHUP, sighup_handler); + errno = save_errno; } /* * Called from the main program after receiving SIGHUP. * Restarts the server. */ -void +static void sighup_restart(void) { log("Received SIGHUP; restarting."); close_listen_socks(); + close_startup_pipes(); execv(saved_argv[0], saved_argv); - log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], strerror(errno)); + log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], + 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. */ -void +static void sigterm_handler(int sig) { - log("Received signal %d; terminating.", sig); - close_listen_socks(); - unlink(options.pid_file); - exit(255); + received_sigterm = sig; } /* * SIGCHLD handler. This is called whenever a child dies. This will then - * reap any zombies left by exited c. + * reap any zombies left by exited children. */ -void +static void main_sigchld_handler(int sig) { int save_errno = errno; + pid_t pid; int status; - while (waitpid(-1, &status, WNOHANG) > 0) + while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || + (pid < 0 && errno == EINTR)) ; signal(SIGCHLD, main_sigchld_handler); @@ -258,9 +299,11 @@ /* * Signal handler for the alarm after the login grace period has expired. */ -void +static void grace_alarm_handler(int sig) { + /* XXX no idea how fix this signal handler */ + /* Close the connection. */ packet_close(); @@ -275,7 +318,7 @@ * Thus there should be no concurrency control/asynchronous execution * problems. */ -void +static void generate_ephemeral_server_key(void) { u_int32_t rand = 0; @@ -298,16 +341,17 @@ arc4random_stir(); } -void +static void key_regeneration_alarm(int sig) { int save_errno = errno; + signal(SIGALRM, SIG_DFL); errno = save_errno; key_do_regen = 1; } -void +static void sshd_exchange_identification(int sock_in, int sock_out) { int i, mismatch; @@ -333,17 +377,18 @@ if (client_version_string == NULL) { /* Send our protocol version identification. */ - if (atomicio(write, sock_out, server_version_string, strlen(server_version_string)) + if (atomicio(write, sock_out, server_version_string, + strlen(server_version_string)) != strlen(server_version_string)) { - log("Could not write ident string to %s.", get_remote_ipaddr()); + log("Could not write ident string to %s", get_remote_ipaddr()); fatal_cleanup(); } - /* Read other side's version identification. */ + /* Read other sides version identification. */ memset(buf, 0, sizeof(buf)); for (i = 0; i < sizeof(buf) - 1; i++) { if (atomicio(read, sock_in, &buf[i], 1) != 1) { - log("Did not receive identification string from %s.", + log("Did not receive identification string from %s", get_remote_ipaddr()); fatal_cleanup(); } @@ -379,7 +424,7 @@ fatal_cleanup(); } debug("Client protocol version %d.%d; client software version %.100s", - remote_major, remote_minor, remote_version); + remote_major, remote_minor, remote_version); compat_datafellows(remote_version); @@ -390,7 +435,7 @@ } mismatch = 0; - switch(remote_major) { + switch (remote_major) { case 1: if (remote_minor == 99) { if (options.protocol & SSH_PROTO_2) @@ -434,11 +479,8 @@ server_version_string, client_version_string); fatal_cleanup(); } - if (compat20) - packet_set_ssh2_format(); } - /* Destroy the host and server keys. They will no longer be needed. */ void destroy_sensitive_data(void) @@ -449,7 +491,7 @@ key_free(sensitive_data.server_key); sensitive_data.server_key = NULL; } - for(i = 0; i < options.num_host_key_files; i++) { + for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { key_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = NULL; @@ -459,36 +501,210 @@ memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); } -char * +/* Demote private to public keys for network child */ +void +demote_sensitive_data(void) +{ + Key *tmp; + int i; + + if (sensitive_data.server_key) { + tmp = key_demote(sensitive_data.server_key); + key_free(sensitive_data.server_key); + sensitive_data.server_key = tmp; + } + + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { + tmp = key_demote(sensitive_data.host_keys[i]); + key_free(sensitive_data.host_keys[i]); + sensitive_data.host_keys[i] = tmp; + if (tmp->type == KEY_RSA1) + sensitive_data.ssh1_host_key = tmp; + } + } + + /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ +} + +static void +privsep_preauth_child(void) +{ + u_int32_t rand[256]; + gid_t gidset[2]; + struct passwd *pw; + int i; + + /* Enable challenge-response authentication for privilege separation */ + privsep_challenge_enable(); + + for (i = 0; i < 256; i++) + rand[i] = arc4random(); + RAND_seed(rand, sizeof(rand)); + + /* Demote the private keys to public keys. */ + demote_sensitive_data(); + + if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) + fatal("Privilege separation user %s does not exist", + SSH_PRIVSEP_USER); + memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); + endpwent(); + + /* Change our root directory*/ + if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) + fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, + strerror(errno)); + if (chdir("/") == -1) + fatal("chdir(\"/\"): %s", strerror(errno)); + + /* Drop our privileges */ + debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, + (u_int)pw->pw_gid); +#if 0 + /* XXX not ready, to heavy after chroot */ + do_setusercontext(pw); +#else + gidset[0] = pw->pw_gid; + if (setgid(pw->pw_gid) < 0) + fatal("setgid failed for %u", pw->pw_gid ); + if (setgroups(1, gidset) < 0) + fatal("setgroups: %.100s", strerror(errno)); + permanently_set_uid(pw); +#endif +} + +static Authctxt* +privsep_preauth(void) +{ + Authctxt *authctxt = NULL; + int status; + pid_t pid; + + /* Set up unprivileged child process to deal with network data */ + pmonitor = monitor_init(); + /* Store a pointer to the kex for later rekeying */ + pmonitor->m_pkex = &xxx_kex; + + pid = fork(); + if (pid == -1) { + fatal("fork of unprivileged child failed"); + } else if (pid != 0) { + debug2("Network child is on pid %ld", (long)pid); + + close(pmonitor->m_recvfd); + authctxt = monitor_child_preauth(pmonitor); + close(pmonitor->m_sendfd); + + /* Sync memory */ + monitor_sync(pmonitor); + + /* Wait for the child's exit status */ + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) + break; + return (authctxt); + } else { + /* child */ + + close(pmonitor->m_sendfd); + + /* Demote the child */ + if (getuid() == 0 || geteuid() == 0) + privsep_preauth_child(); + setproctitle("%s", "[net]"); + } + return (NULL); +} + +static void +privsep_postauth(Authctxt *authctxt) +{ + extern Authctxt *x_authctxt; + + /* XXX - Remote port forwarding */ + x_authctxt = authctxt; + +#ifdef BROKEN_FD_PASSING + if (1) { +#else + if (authctxt->pw->pw_uid == 0 || options.use_login) { +#endif + /* File descriptor passing is broken or root login */ + monitor_apply_keystate(pmonitor); + use_privsep = 0; + return; + } + + /* Authentication complete */ + alarm(0); + if (startup_pipe != -1) { + close(startup_pipe); + startup_pipe = -1; + } + + /* New socket pair */ + monitor_reinit(pmonitor); + + pmonitor->m_pid = fork(); + if (pmonitor->m_pid == -1) + fatal("fork of unprivileged child failed"); + else if (pmonitor->m_pid != 0) { + debug2("User child is on pid %ld", (long)pmonitor->m_pid); + close(pmonitor->m_recvfd); + monitor_child_postauth(pmonitor); + + /* NEVERREACHED */ + exit(0); + } + + close(pmonitor->m_sendfd); + + /* Demote the private keys to public keys. */ + demote_sensitive_data(); + + /* Drop privileges */ + do_setusercontext(authctxt->pw); + + /* It is safe now to apply the key state */ + monitor_apply_keystate(pmonitor); +} + +static char * list_hostkey_types(void) { - static char buf[1024]; + Buffer b; + char *p; int i; - buf[0] = '\0'; - for(i = 0; i < options.num_host_key_files; i++) { + + buffer_init(&b); + for (i = 0; i < options.num_host_key_files; i++) { Key *key = sensitive_data.host_keys[i]; if (key == NULL) continue; - switch(key->type) { + switch (key->type) { case KEY_RSA: case KEY_DSA: - strlcat(buf, key_ssh_name(key), sizeof buf); - strlcat(buf, ",", sizeof buf); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + p = key_ssh_name(key); + buffer_append(&b, p, strlen(p)); break; } } - i = strlen(buf); - if (i > 0 && buf[i-1] == ',') - buf[i-1] = '\0'; - debug("list_hostkey_types: %s", buf); - return buf; + buffer_append(&b, "\0", 1); + p = xstrdup(buffer_ptr(&b)); + buffer_free(&b); + debug("list_hostkey_types: %s", p); + return p; } Key * get_hostkey_by_type(int type) { int i; - for(i = 0; i < options.num_host_key_files; i++) { + + for (i = 0; i < options.num_host_key_files; i++) { Key *key = sensitive_data.host_keys[i]; if (key != NULL && key->type == type) return key; @@ -496,13 +712,33 @@ return NULL; } +Key * +get_hostkey_by_index(int ind) +{ + if (ind < 0 || ind >= options.num_host_key_files) + return (NULL); + return (sensitive_data.host_keys[ind]); +} + +int +get_hostkey_index(Key *key) +{ + int i; + + for (i = 0; i < options.num_host_key_files; i++) { + if (key == sensitive_data.host_keys[i]) + return (i); + } + return (-1); +} + /* * returns 1 if connection should be dropped, 0 otherwise. * dropping starts at connection #max_startups_begin with a probability * of (max_startups_rate/100). the probability increases linearly until * all connections are dropped for startups > max_startups */ -int +static int drop_connection(int startups) { double p, r; @@ -525,8 +761,30 @@ return (r < p) ? 1 : 0; } -int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ -int startup_pipe; /* in child */ +static void +usage(void) +{ + fprintf(stderr, "sshd version %s\n", SSH_VERSION); + fprintf(stderr, "Usage: %s [options]\n", __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE); + fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n"); + fprintf(stderr, " -i Started from inetd\n"); + fprintf(stderr, " -D Do not fork into daemon mode\n"); + fprintf(stderr, " -t Only test configuration file and keys\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: 600)\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", + _PATH_HOST_KEY_FILE); + fprintf(stderr, " -u len Maximum hostname length for utmp recording\n"); + fprintf(stderr, " -4 Use IPv4 only\n"); + fprintf(stderr, " -6 Use IPv6 only\n"); + fprintf(stderr, " -o option Process the option as if it was read from a configuration file.\n"); + exit(1); +} /* * Main program for the daemon. @@ -550,17 +808,25 @@ int listen_sock, maxfd; int startup_p[2]; int startups = 0; + Authctxt *authctxt; Key *key; int ret, key_used = 0; +#ifdef HAVE_SECUREWARE + (void)set_auth_parameters(ac, av); +#endif + __progname = get_progname(av[0]); + init_rng(); + /* Save argv. */ + saved_argc = ac; saved_argv = av; /* 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:V:u:dDeiqQ46")) != -1) { + while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) { switch (opt) { case '4': IPv4or6 = AF_INET; @@ -613,10 +879,16 @@ } break; case 'g': - options.login_grace_time = atoi(optarg); + if ((options.login_grace_time = convtime(optarg)) == -1) { + fprintf(stderr, "Invalid login grace time.\n"); + exit(1); + } break; case 'k': - options.key_regeneration_time = atoi(optarg); + if ((options.key_regeneration_time = convtime(optarg)) == -1) { + fprintf(stderr, "Invalid key regeneration interval.\n"); + exit(1); + } break; case 'h': if (options.num_host_key_files >= MAX_HOSTKEYS) { @@ -630,42 +902,46 @@ /* only makes sense with inetd_flag, i.e. no listen() */ inetd_flag = 1; break; + case 't': + test_flag = 1; + break; case 'u': utmp_len = atoi(optarg); break; + case 'o': + if (process_server_config_line(&options, optarg, + "command-line", 0) != 0) + exit(1); + break; case '?': default: - fprintf(stderr, "sshd version %s\n", SSH_VERSION); - fprintf(stderr, "Usage: %s [options]\n", __progname); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE); - fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n"); - fprintf(stderr, " -i Started from inetd\n"); - fprintf(stderr, " -D Do not fork into daemon mode\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: 600)\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", - _PATH_HOST_KEY_FILE); - fprintf(stderr, " -u len Maximum hostname length for utmp recording\n"); - fprintf(stderr, " -4 Use IPv4 only\n"); - fprintf(stderr, " -6 Use IPv6 only\n"); - exit(1); + usage(); + break; } } SSLeay_add_all_algorithms(); + channel_set_af(IPv4or6); /* * Force logging to stderr until we have loaded the private host * key (unless started from inetd) */ log_init(__progname, - options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, - options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility, + options.log_level == SYSLOG_LEVEL_NOT_SET ? + SYSLOG_LEVEL_INFO : options.log_level, + options.log_facility == SYSLOG_FACILITY_NOT_SET ? + SYSLOG_FACILITY_AUTH : options.log_facility, !inetd_flag); +#ifdef _CRAY + /* Cray can define user privs drop all prives now! + * Not needed on PRIV_SU systems! + */ + drop_cray_privs(); +#endif + + seed_rng(); + /* Read server configuration options from the configuration file. */ read_server_config(&options, config_file_name); @@ -682,14 +958,14 @@ /* load private host keys */ sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*)); - for(i = 0; i < options.num_host_key_files; i++) + for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_keys[i] = NULL; sensitive_data.server_key = NULL; sensitive_data.ssh1_host_key = NULL; sensitive_data.have_ssh1_key = 0; sensitive_data.have_ssh2_key = 0; - for(i = 0; i < options.num_host_key_files; i++) { + for (i = 0; i < options.num_host_key_files; i++) { key = key_load_private(options.host_key_files[i], "", NULL); sensitive_data.host_keys[i] = key; if (key == NULL) { @@ -698,7 +974,7 @@ sensitive_data.host_keys[i] = NULL; continue; } - switch(key->type){ + switch (key->type) { case KEY_RSA1: sensitive_data.ssh1_host_key = key; sensitive_data.have_ssh1_key = 1; @@ -737,16 +1013,48 @@ * hate software patents. I dont know if this can go? Niels */ if (options.server_key_bits > - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - SSH_KEY_BITS_RESERVED && - options.server_key_bits < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - + SSH_KEY_BITS_RESERVED && options.server_key_bits < + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + + SSH_KEY_BITS_RESERVED) { options.server_key_bits = - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED; + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + + SSH_KEY_BITS_RESERVED; debug("Forcing server key to %d bits to make it differ from host key.", options.server_key_bits); } } + if (use_privsep) { + struct passwd *pw; + struct stat st; + + if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) + fatal("Privilege separation user %s does not exist", + SSH_PRIVSEP_USER); + if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || + (S_ISDIR(st.st_mode) == 0)) + fatal("Missing privilege separation directory: %s", + _PATH_PRIVSEP_CHROOT_DIR); + if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) + fatal("Bad owner or mode for %s", + _PATH_PRIVSEP_CHROOT_DIR); + } + + /* Configuration looks good, so exit if in test mode. */ + if (test_flag) + exit(0); + + /* + * Clear out any supplemental groups we may have inherited. This + * prevents inadvertent creation of files with bad modes (in the + * portable version at least, it's certainly possible for PAM + * to create a file, and we can't control the code in every + * module which might be used). + */ + if (setgroups(0, NULL) < 0) + debug("setgroups() failed: %.200s", strerror(errno)); + /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && !inetd_flag) log_stderr = 1; @@ -782,7 +1090,7 @@ /* Chdir to the root directory so that the current disk can be unmounted if desired. */ chdir("/"); - + /* ignore SIGPIPE */ signal(SIGPIPE, SIG_IGN); @@ -834,18 +1142,19 @@ * close. */ setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, - (void *) &on, sizeof(on)); + &on, sizeof(on)); linger.l_onoff = 1; linger.l_linger = 5; setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, - (void *) &linger, sizeof(linger)); + &linger, sizeof(linger)); debug("Bind to port %s on %s.", strport, ntop); /* Bind the socket to the desired port. */ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { - error("Bind to port %s on %s failed: %.200s.", - strport, ntop, strerror(errno)); + if (!ai->ai_next) + error("Bind to port %s on %s failed: %.200s.", + strport, ntop, strerror(errno)); close(listen_sock); continue; } @@ -863,6 +1172,22 @@ if (!num_listen_socks) fatal("Cannot bind any address."); + if (options.protocol & SSH_PROTO_1) + generate_ephemeral_server_key(); + + /* + * 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); + + /* Write out the pid file after the sigterm handler is setup */ if (!debug_flag) { /* * Record our pid in /var/run/sshd.pid to make it @@ -871,23 +1196,12 @@ * fail if there already is a daemon, and this will * overwrite any old pid in the file. */ - f = fopen(options.pid_file, "w"); + f = fopen(options.pid_file, "wb"); if (f) { - fprintf(f, "%u\n", (u_int) getpid()); + fprintf(f, "%ld\n", (long) getpid()); fclose(f); } } - if (options.protocol & SSH_PROTO_1) - generate_ephemeral_server_key(); - - /* 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); /* setup fd set for listen */ fdset = NULL; @@ -923,6 +1237,13 @@ ret = select(maxfd+1, fdset, NULL, NULL, NULL); if (ret < 0 && errno != EINTR) error("select: %.100s", strerror(errno)); + if (received_sigterm) { + log("Received signal %d; terminating.", + (int) received_sigterm); + close_listen_socks(); + unlink(options.pid_file); + exit(255); + } if (key_used && key_do_regen) { generate_ephemeral_server_key(); key_used = 0; @@ -957,6 +1278,7 @@ } if (fcntl(newsock, F_SETFL, 0) < 0) { error("newsock del O_NONBLOCK: %s", strerror(errno)); + close(newsock); continue; } if (drop_connection(startups) == 1) { @@ -1010,9 +1332,7 @@ * the connection. */ startup_pipe = startup_p[1]; - for (j = 0; j < options.max_startups; j++) - if (startup_pipes[j] != -1) - close(startup_pipes[j]); + close_startup_pipes(); close_listen_socks(); sock_in = newsock; sock_out = newsock; @@ -1025,7 +1345,7 @@ if (pid < 0) error("fork: %.100s", strerror(errno)); else - debug("Forked child %d.", pid); + debug("Forked child %ld.", (long)pid); close(startup_p[1]); @@ -1052,6 +1372,17 @@ /* This is the child processing a new connection. */ /* + * Create a new session and process group since the 4.4BSD + * setlogin() affects the entire process group. We don't + * want the child to be able to affect the parent. + */ +#if 0 + /* XXX: this breaks Solaris */ + if (!debug_flag && !inetd_flag && setsid() < 0) + error("setsid: %.100s", strerror(errno)); +#endif + + /* * 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. @@ -1062,7 +1393,7 @@ signal(SIGTERM, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGCHLD, SIG_DFL); - signal(SIGPIPE, SIG_IGN); + signal(SIGINT, SIG_DFL); /* * Set socket options for the connection. We want the socket to @@ -1072,11 +1403,11 @@ /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ linger.l_onoff = 1; linger.l_linger = 5; - setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); + setsockopt(sock_in, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); /* Set keepalives if requested. */ if (options.keepalives && - setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, + setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); @@ -1089,22 +1420,23 @@ remote_port = get_remote_port(); remote_ip = get_remote_ipaddr(); - /* Check whether logins are denied from this host. */ #ifdef LIBWRAP + /* Check whether logins are denied from this host. */ { struct request_info req; - request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, NULL); + request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); fromhost(&req); if (!hosts_access(&req)) { + debug("Connection refused by tcp wrapper"); refuse(&req); - close(sock_in); - close(sock_out); + /* NOTREACHED */ + fatal("libwrap refuse returns"); } - verbose("Connection from %.500s port %d", eval_client(&req), remote_port); } #endif /* LIBWRAP */ + /* Log the connection. */ verbose("Connection from %.500s port %d", remote_ip, remote_port); @@ -1123,15 +1455,16 @@ sshd_exchange_identification(sock_in, sock_out); /* * Check that the connection comes from a privileged port. - * Rhosts-Authentication only makes sense from priviledged + * Rhosts-Authentication only makes sense from privileged * programs. Of course, if the intruder has root access on his local * machine, he can connect from any port. So do not use these * authentication methods from machines that you do not trust. */ - if (remote_port >= IPPORT_RESERVED || - remote_port < IPPORT_RESERVED / 2) { + if (options.rhosts_authentication && + (remote_port >= IPPORT_RESERVED || + remote_port < IPPORT_RESERVED / 2)) { debug("Rhosts Authentication disabled, " - "originating port not trusted."); + "originating port %d not trusted.", remote_port); options.rhosts_authentication = 0; } #if defined(KRB4) && !defined(KRB5) @@ -1140,7 +1473,7 @@ debug("Kerberos Authentication disabled, only available for IPv4."); options.kerberos_authentication = 0; } -#endif /* KRB4 */ +#endif /* KRB4 && !KRB5 */ #ifdef AFS /* If machine has AFS, set process authentication group. */ if (k_hasafs()) { @@ -1151,21 +1484,42 @@ packet_set_nonblocking(); + if (use_privsep) + if ((authctxt = privsep_preauth()) != NULL) + goto authenticated; + /* perform the key exchange */ /* authenticate user and start session */ if (compat20) { do_ssh2_kex(); - do_authentication2(); + authctxt = do_authentication2(); } else { do_ssh1_kex(); - do_authentication(); + authctxt = do_authentication(); + } + /* + * If we use privilege separation, the unprivileged child transfers + * the current keystate and exits + */ + if (use_privsep) { + mm_send_keystate(pmonitor); + exit(0); + } + + authenticated: + /* + * In privilege separation, we fork another child and prepare + * file descriptor passing. + */ + if (use_privsep) { + privsep_postauth(authctxt); + /* the monitor process [priv] will not return */ + if (!compat20) + destroy_sensitive_data(); } -#ifdef KRB4 - /* Cleanup user's ticket cache file. */ - if (options.krb4_ticket_cleanup) - (void) dest_tkt(); -#endif /* KRB4 */ + /* Perform session preparation. */ + do_authenticated(authctxt); /* The connection has been terminated. */ verbose("Closing connection to %.100s", remote_ip); @@ -1175,17 +1529,64 @@ #endif /* USE_PAM */ packet_close(); + + if (use_privsep) + mm_terminate(); + exit(0); } /* + * Decrypt session_key_int using our private server key and private host key + * (key with larger modulus first). + */ +int +ssh1_session_key(BIGNUM *session_key_int) +{ + int rsafail = 0; + + if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { + /* Server key has bigger modulus. */ + if (BN_num_bits(sensitive_data.server_key->rsa->n) < + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", + get_remote_ipaddr(), + BN_num_bits(sensitive_data.server_key->rsa->n), + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), + SSH_KEY_BITS_RESERVED); + } + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.server_key->rsa) <= 0) + rsafail++; + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.ssh1_host_key->rsa) <= 0) + rsafail++; + } else { + /* Host key has bigger modulus (or they are equal). */ + if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < + BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", + get_remote_ipaddr(), + BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), + BN_num_bits(sensitive_data.server_key->rsa->n), + SSH_KEY_BITS_RESERVED); + } + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.ssh1_host_key->rsa) < 0) + rsafail++; + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.server_key->rsa) < 0) + rsafail++; + } + return (rsafail); +} +/* * SSH1 key exchange */ -void +static void do_ssh1_kex(void) { int i, len; - int plen, slen; int rsafail = 0; BIGNUM *session_key_int; u_char session_key[SSH_SESSION_KEY_LENGTH]; @@ -1246,18 +1647,15 @@ if (options.kerberos_authentication) auth_mask |= 1 << SSH_AUTH_KERBEROS; #endif -#ifdef KRB5 - if (options.krb5_tgt_passing) - auth_mask |= 1 << SSH_PASS_KERBEROS_TGT; -#endif /* KRB5 */ - -#ifdef AFS - if (options.krb4_tgt_passing) +#if defined(AFS) || defined(KRB5) + if (options.kerberos_tgt_passing) auth_mask |= 1 << SSH_PASS_KERBEROS_TGT; +#endif +#ifdef AFS if (options.afs_token_passing) auth_mask |= 1 << SSH_PASS_AFS_TOKEN; #endif - if (options.challenge_reponse_authentication == 1) + if (options.challenge_response_authentication == 1) auth_mask |= 1 << SSH_AUTH_TIS; if (options.password_authentication) auth_mask |= 1 << SSH_AUTH_PASSWORD; @@ -1272,7 +1670,7 @@ BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); /* Read clients reply (cipher type and session key). */ - packet_read_expect(&plen, SSH_CMSG_SESSION_KEY); + packet_read_expect(SSH_CMSG_SESSION_KEY); /* Get cipher type and check whether we accept this. */ cipher_type = packet_get_char(); @@ -1289,52 +1687,18 @@ debug("Encryption type: %.200s", cipher_name(cipher_type)); /* Get the encrypted integer. */ - session_key_int = BN_new(); - packet_get_bignum(session_key_int, &slen); + if ((session_key_int = BN_new()) == NULL) + fatal("do_ssh1_kex: BN_new failed"); + packet_get_bignum(session_key_int); protocol_flags = packet_get_int(); packet_set_protocol_flags(protocol_flags); + packet_check_eom(); - packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY); + /* Decrypt session_key_int using host/server keys */ + rsafail = PRIVSEP(ssh1_session_key(session_key_int)); /* - * Decrypt it using our private server key and private host key (key - * with larger modulus first). - */ - if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { - /* Server key has bigger modulus. */ - if (BN_num_bits(sensitive_data.server_key->rsa->n) < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), - BN_num_bits(sensitive_data.server_key->rsa->n), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) <= 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) <= 0) - rsafail++; - } else { - /* Host key has bigger modulus (or they are equal). */ - if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < - BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", - get_remote_ipaddr(), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - BN_num_bits(sensitive_data.server_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) < 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) < 0) - rsafail++; - } - /* * 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. @@ -1365,7 +1729,7 @@ } if (rsafail) { int bytes = BN_num_bytes(session_key_int); - char *buf = xmalloc(bytes); + u_char *buf = xmalloc(bytes); MD5_CTX md; log("do_connection: generating a fake encryption key"); @@ -1384,9 +1748,12 @@ for (i = 0; i < 16; i++) session_id[i] = session_key[i] ^ session_key[i + 16]; } - /* Destroy the private and public keys. They will no longer be needed. */ + /* Destroy the private and public keys. No longer. */ destroy_sensitive_data(); + if (use_privsep) + mm_ssh1_session_id(session_id); + /* Destroy the decrypted integer. It is no longer needed. */ BN_clear_free(session_key_int); @@ -1398,7 +1765,7 @@ debug("Received session key; encryption turned on."); - /* Send an acknowledgement packet. Note that this packet is sent encrypted. */ + /* Send an acknowledgment packet. Note that this packet is sent encrypted. */ packet_start(SSH_SMSG_SUCCESS); packet_send(); packet_write_wait(); @@ -1407,7 +1774,7 @@ /* * SSH2 key exchange: diffie-hellman-group1-sha1 */ -void +static void do_ssh2_kex(void) { Kex *kex; @@ -1425,6 +1792,10 @@ myproposal[PROPOSAL_MAC_ALGS_CTOS] = myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; } + if (!options.compression) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; + } myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); /* start key exchange */ @@ -1433,6 +1804,7 @@ kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->load_host_key=&get_hostkey_by_type; + kex->host_key_index=&get_hostkey_index; xxx_kex = kex; Index: src/crypto/openssh/sshd_config =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshd_config,v retrieving revision 1.4.2.8 diff -u -u -r1.4.2.8 sshd_config --- src/crypto/openssh/sshd_config 25 Apr 2002 16:53:25 -0000 1.4.2.8 +++ src/crypto/openssh/sshd_config 1 Jul 2002 14:58:58 -0000 @@ -1,70 +1,98 @@ -# $OpenBSD: sshd_config,v 1.38 2001/04/15 21:41:29 deraadt Exp $ -# $FreeBSD: src/crypto/openssh/sshd_config,v 1.4.2.8 2002/04/25 16:53:25 des Exp $ +# $OpenBSD: sshd_config,v 1.56 2002/06/20 23:37:12 markus Exp $ +# $FreeBSD: src/crypto/openssh/sshd_config,v 1.26 2002/06/30 10:32:09 des Exp $ -# This is the sshd server system-wide configuration file. See sshd(8) -# for more information. +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. -Port 22 +# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options change a +# default value. + +# Note that some of FreeBSD's defaults differ from OpenBSD's, and +# FreeBSD has a few additional options. + +#VersionAddendum FreeBSD-20020629 + +#Port 22 #Protocol 2,1 #ListenAddress 0.0.0.0 #ListenAddress :: -HostKey /etc/ssh/ssh_host_key -HostKey /etc/ssh/ssh_host_dsa_key -ServerKeyBits 768 -LoginGraceTime 120 -KeyRegenerationInterval 3600 -PermitRootLogin no -# ConnectionsPerPeriod has been deprecated completely - -# After 10 unauthenticated connections, refuse 30% of the new ones, and -# refuse any more than 60 total. -MaxStartups 10:30:60 -# Don't read ~/.rhosts and ~/.shosts files -IgnoreRhosts yes -# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication -#IgnoreUserKnownHosts yes -StrictModes yes -X11Forwarding yes -X11DisplayOffset 10 -PrintMotd yes -#PrintLastLog no -KeepAlive yes + +# HostKey for protocol version 1 +#HostKey /etc/ssh/ssh_host_key +# HostKeys for protocol version 2 +#HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_dsa_key + +# Lifetime and size of ephemeral version 1 server key +#KeyRegenerationInterval 3600 +#ServerKeyBits 768 # Logging -SyslogFacility AUTH -LogLevel INFO #obsoletes QuietMode and FascistLogging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: -RhostsAuthentication no -# -# For this to work you will also need host keys in /etc/ssh_known_hosts -RhostsRSAAuthentication no +#LoginGraceTime 120 +#PermitRootLogin no +#StrictModes yes + +#RSAAuthentication yes +#PubkeyAuthentication yes +#AuthorizedKeysFile .ssh/authorized_keys + +# rhosts authentication should not be used +#RhostsAuthentication no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#RhostsRSAAuthentication no # similar for protocol version 2 -HostbasedAuthentication no -# -RSAAuthentication yes +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# RhostsRSAAuthentication and HostbasedAuthentication +#IgnoreUserKnownHosts no # To disable tunneled clear text passwords, change to no here! -PasswordAuthentication yes -PermitEmptyPasswords no +#PasswordAuthentication yes +#PermitEmptyPasswords no -# Uncomment to disable s/key passwords -#ChallengeResponseAuthentication no +# Change to no to disable s/key passwords +#ChallengeResponseAuthentication yes -# To change Kerberos options +# Kerberos options #KerberosAuthentication no #KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes + #AFSTokenPassing no -#KerberosTicketCleanup no -# Kerberos TGT Passing does only work with the AFS kaserver -#KerberosTgtPassing yes +# Kerberos TGT Passing only works with the AFS kaserver +#KerberosTgtPassing no -CheckMail yes +# Set this to 'yes' to enable PAM keyboard-interactive authentication +# Warning: enabling this may bypass the setting of 'PasswordAuthentication' +#PAMAuthenticationViaKbdInt yes + +#X11Forwarding yes +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PrintMotd yes +#PrintLastLog yes +#KeepAlive yes #UseLogin no +#UsePrivilegeSeparation no +#Compression yes -#MaxStartups 10:30:60 -#Banner /etc/issue.net -#ReverseMappingCheck yes +#MaxStartups 10 +# no default banner path +#Banner /some/path +#VerifyReverseMapping no +# override default of no subsystems Subsystem sftp /usr/libexec/sftp-server Index: src/crypto/openssh/sshd_config.5 =================================================================== RCS file: src/crypto/openssh/sshd_config.5 diff -N src/crypto/openssh/sshd_config.5 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/sshd_config.5 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,722 @@ +.\" -*- nroff -*- +.\" +.\" Author: Tatu Ylonen +.\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland +.\" All rights reserved +.\" +.\" 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". +.\" +.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. +.\" Copyright (c) 1999 Aaron Campbell. All rights reserved. +.\" Copyright (c) 1999 Theo de Raadt. 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $OpenBSD: sshd_config.5,v 1.4 2002/06/22 16:45:29 stevesk Exp $ +.\" $FreeBSD: src/crypto/openssh/sshd_config.5,v 1.5 2002/06/29 11:48:59 des Exp $ +.Dd September 25, 1999 +.Dt SSHD_CONFIG 5 +.Os +.Sh NAME +.Nm sshd_config +.Nd OpenSSH SSH daemon configuration file +.Sh SYNOPSIS +.Bl -tag -width Ds -compact +.It Pa /etc/ssh/sshd_config +.El +.Sh DESCRIPTION +.Nm sshd +reads configuration data from +.Pa /etc/ssh/sshd_config +(or the file specified with +.Fl f +on the command line). +The file contains keyword-argument pairs, one per line. +Lines starting with +.Ql # +and empty lines are interpreted as comments. +.Pp +The possible +keywords and their meanings are as follows (note that +keywords are case-insensitive and arguments are case-sensitive): +.Bl -tag -width Ds +.It Cm AFSTokenPassing +Specifies whether an AFS token may be forwarded to the server. +Default is +.Dq no . +.It Cm AllowGroups +This keyword can be followed by a list of group name patterns, separated +by spaces. +If specified, login is allowed only for users whose primary +group or supplementary group list matches one of the patterns. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. +Only group names are valid; a numerical group ID is not recognized. +By default, login is allowed for all groups. +.Pp +.It Cm AllowTcpForwarding +Specifies whether TCP forwarding is permitted. +The default is +.Dq yes . +Note that disabling TCP forwarding does not improve security unless +users are also denied shell access, as they can always install their +own forwarders. +.Pp +.It Cm AllowUsers +This keyword can be followed by a list of user name patterns, separated +by spaces. +If specified, login is allowed only for users names that +match one of the patterns. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. +Only user names are valid; a numerical user ID is not recognized. +By default, login is allowed for all users. +If the pattern takes the form USER@HOST then USER and HOST +are separately checked, restricting logins to particular +users from particular hosts. +.Pp +.It Cm AuthorizedKeysFile +Specifies the file that contains the public keys that can be used +for user authentication. +.Cm AuthorizedKeysFile +may contain tokens of the form %T which are substituted during connection +set-up. The following tokens are defined: %% is replaced by a literal '%', +%h is replaced by the home directory of the user being authenticated and +%u is replaced by the username of that user. +After expansion, +.Cm AuthorizedKeysFile +is taken to be an absolute path or one relative to the user's home +directory. +The default is +.Dq .ssh/authorized_keys . +.It Cm Banner +In some jurisdictions, sending a warning message before authentication +may be relevant for getting legal protection. +The contents of the specified file are sent to the remote user before +authentication is allowed. +This option is only available for protocol version 2. +By default, no banner is displayed. +.Pp +.It Cm ChallengeResponseAuthentication +Specifies whether challenge response authentication is allowed. +All authentication styles from +.Xr login.conf 5 +are supported. +The default is +.Dq yes . +.It Cm Ciphers +Specifies the ciphers allowed for protocol version 2. +Multiple ciphers must be comma-separated. +The default is +.Pp +.Bd -literal + ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, + aes192-cbc,aes256-cbc'' +.Ed +.It Cm ClientAliveInterval +Sets a timeout interval in seconds after which if no data has been received +from the client, +.Nm sshd +will send a message through the encrypted +channel to request a response from the client. +The default +is 0, indicating that these messages will not be sent to the client. +This option applies to protocol version 2 only. +.It Cm ClientAliveCountMax +Sets the number of client alive messages (see above) which may be +sent without +.Nm sshd +receiving any messages back from the client. If this threshold is +reached while client alive messages are being sent, +.Nm sshd +will disconnect the client, terminating the session. It is important +to note that the use of client alive messages is very different from +.Cm KeepAlive +(below). The client alive messages are sent through the +encrypted channel and therefore will not be spoofable. The TCP keepalive +option enabled by +.Cm KeepAlive +is spoofable. The client alive mechanism is valuable when the client or +server depend on knowing when a connection has become inactive. +.Pp +The default value is 3. If +.Cm ClientAliveInterval +(above) is set to 15, and +.Cm ClientAliveCountMax +is left at the default, unresponsive ssh clients +will be disconnected after approximately 45 seconds. +.It Cm Compression +Specifies whether compression is allowed. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq yes . +.It Cm DenyGroups +This keyword can be followed by a list of group name patterns, separated +by spaces. +Login is disallowed for users whose primary group or supplementary +group list matches one of the patterns. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. +Only group names are valid; a numerical group ID is not recognized. +By default, login is allowed for all groups. +.Pp +.It Cm DenyUsers +This keyword can be followed by a list of user name patterns, separated +by spaces. +Login is disallowed for user names that match one of the patterns. +.Ql \&* +and +.Ql ? +can be used as wildcards in the patterns. +Only user names are valid; a numerical user ID is not recognized. +By default, login is allowed for all users. +If the pattern takes the form USER@HOST then USER and HOST +are separately checked, restricting logins to particular +users from particular hosts. +.It Cm GatewayPorts +Specifies whether remote hosts are allowed to connect to ports +forwarded for the client. +By default, +.Nm sshd +binds remote port forwardings to the loopback address. This +prevents other remote hosts from connecting to forwarded ports. +.Cm GatewayPorts +can be used to specify that +.Nm sshd +should bind remote port forwardings to the wildcard address, +thus allowing remote hosts to connect to forwarded ports. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . +.It Cm HostbasedAuthentication +Specifies whether rhosts or /etc/hosts.equiv authentication together +with successful public key client host authentication is allowed +(hostbased authentication). +This option is similar to +.Cm RhostsRSAAuthentication +and applies to protocol version 2 only. +The default is +.Dq no . +.It Cm HostKey +Specifies a file containing a private host key +used by SSH. +The default is +.Pa /etc/ssh/ssh_host_key +for protocol version 1, and +.Pa /etc/ssh/ssh_host_rsa_key +and +.Pa /etc/ssh/ssh_host_dsa_key +for protocol version 2. +Note that +.Nm sshd +will refuse to use a file if it is group/world-accessible. +It is possible to have multiple host key files. +.Dq rsa1 +keys are used for version 1 and +.Dq dsa +or +.Dq rsa +are used for version 2 of the SSH protocol. +.It Cm IgnoreRhosts +Specifies that +.Pa .rhosts +and +.Pa .shosts +files will not be used in +.Cm RhostsAuthentication , +.Cm RhostsRSAAuthentication +or +.Cm HostbasedAuthentication . +.Pp +.Pa /etc/hosts.equiv +and +.Pa /etc/ssh/shosts.equiv +are still used. +The default is +.Dq yes . +.It Cm IgnoreUserKnownHosts +Specifies whether +.Nm sshd +should ignore the user's +.Pa $HOME/.ssh/known_hosts +during +.Cm RhostsRSAAuthentication +or +.Cm HostbasedAuthentication . +The default is +.Dq no . +.It Cm KeepAlive +Specifies whether the system should send TCP 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 sent, +sessions may hang indefinitely on the server, leaving +.Dq ghost +users and consuming server resources. +.Pp +The default is +.Dq yes +(to send keepalives), and the server will notice +if the network goes down or the client host crashes. +This avoids infinitely hanging sessions. +.Pp +To disable keepalives, the value should be set to +.Dq no . +.It Cm KerberosAuthentication +Specifies whether Kerberos authentication is allowed. +This can be in the form of a Kerberos ticket, or if +.Cm PasswordAuthentication +is yes, the password provided by the user will be validated through +the Kerberos KDC. +To use this option, the server needs a +Kerberos servtab which allows the verification of the KDC's identity. +Default is +.Dq no . +.It Cm KerberosOrLocalPasswd +If set then if password authentication through Kerberos fails then +the password will be validated via any additional local mechanism +such as +.Pa /etc/passwd . +Default is +.Dq yes . +.It Cm KerberosTgtPassing +Specifies whether a Kerberos TGT may be forwarded to the server. +Default is +.Dq no , +as this only works when the Kerberos KDC is actually an AFS kaserver. +.It Cm KerberosTicketCleanup +Specifies whether to automatically destroy the user's ticket cache +file on logout. +Default is +.Dq yes . +.It Cm KeyRegenerationInterval +In protocol version 1, the ephemeral 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). +.It Cm ListenAddress +Specifies the local addresses +.Nm sshd +should listen on. +The following forms may be used: +.Pp +.Bl -item -offset indent -compact +.It +.Cm ListenAddress +.Sm off +.Ar host No | Ar IPv4_addr No | Ar IPv6_addr +.Sm on +.It +.Cm ListenAddress +.Sm off +.Ar host No | Ar IPv4_addr No : Ar port +.Sm on +.It +.Cm ListenAddress +.Sm off +.Oo +.Ar host No | Ar IPv6_addr Oc : Ar port +.Sm on +.El +.Pp +If +.Ar port +is not specified, +.Nm sshd +will listen on the address and all prior +.Cm Port +options specified. The default is to listen on all local +addresses. Multiple +.Cm ListenAddress +options are permitted. Additionally, any +.Cm Port +options must precede this option for non port qualified addresses. +.It Cm 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 120 (seconds). +.It Cm LogLevel +Gives the verbosity level that is used when logging messages from +.Nm sshd . +The possible values are: +QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3. +The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 +and DEBUG3 each specify higher levels of debugging output. +Logging with a DEBUG level violates the privacy of users +and is not recommended. +.It Cm MACs +Specifies the available MAC (message authentication code) algorithms. +The MAC algorithm is used in protocol version 2 +for data integrity protection. +Multiple algorithms must be comma-separated. +The default is +.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 . +.It Cm MaxStartups +Specifies the maximum number of concurrent unauthenticated connections to the +.Nm sshd +daemon. +Additional connections will be dropped until authentication succeeds or the +.Cm LoginGraceTime +expires for a connection. +The default is 10. +.Pp +Alternatively, random early drop can be enabled by specifying +the three colon separated values +.Dq start:rate:full +(e.g., "10:30:60"). +.Nm sshd +will refuse connection attempts with a probability of +.Dq rate/100 +(30%) +if there are currently +.Dq start +(10) +unauthenticated connections. +The probability increases linearly and all connection attempts +are refused if the number of unauthenticated connections reaches +.Dq full +(60). +.It Cm PAMAuthenticationViaKbdInt +Specifies whether PAM challenge response authentication is allowed. This +allows the use of most PAM challenge response authentication modules, but +it will allow password authentication regardless of whether +.Cm PasswordAuthentication +is enabled. +.It Cm PasswordAuthentication +Specifies whether password authentication is allowed. +The default is +.Dq yes . +.It Cm PermitEmptyPasswords +When password authentication is allowed, it specifies whether the +server allows login to accounts with empty password strings. +The default is +.Dq no . +.It Cm PermitRootLogin +Specifies whether root can login using +.Xr ssh 1 . +The argument must be +.Dq yes , +.Dq without-password , +.Dq forced-commands-only +or +.Dq no . +The default is +.Dq no . +.Pp +If this option is set to +.Dq without-password +password authentication is disabled for root. +.Pp +If this option is set to +.Dq forced-commands-only +root login with public key authentication will be allowed, +but only if the +.Ar command +option has been specified +(which may be useful for taking remote backups even if root login is +normally not allowed). All other authentication methods are disabled +for root. +.Pp +If this option is set to +.Dq no +root is not allowed to login. +.It Cm PidFile +Specifies the file that contains the process ID of the +.Nm sshd +daemon. +The default is +.Pa /var/run/sshd.pid . +.It Cm Port +Specifies the port number that +.Nm sshd +listens on. +The default is 22. +Multiple options of this type are permitted. +See also +.Cm ListenAddress . +.It Cm PrintLastLog +Specifies whether +.Nm sshd +should print the date and time when the user last logged in. +The default is +.Dq yes . +.It Cm PrintMotd +Specifies whether +.Nm sshd +should print +.Pa /etc/motd +when a user logs in interactively. +(On some systems it is also printed by the shell, +.Pa /etc/profile , +or equivalent.) +The default is +.Dq yes . +.It Cm Protocol +Specifies the protocol versions +.Nm sshd +should support. +The possible values are +.Dq 1 +and +.Dq 2 . +Multiple versions must be comma-separated. +The default is +.Dq 2,1 . +.It Cm PubkeyAuthentication +Specifies whether public key authentication is allowed. +The default is +.Dq yes . +Note that this option applies to protocol version 2 only. +.It Cm RhostsAuthentication +Specifies whether authentication using rhosts or +.Pa /etc/hosts.equiv +files is sufficient. +Normally, this method should not be permitted because it is insecure. +.Cm RhostsRSAAuthentication +should be used +instead, because it performs RSA-based host authentication in addition +to normal rhosts or +.Pa /etc/hosts.equiv +authentication. +The default is +.Dq no . +This option applies to protocol version 1 only. +.It Cm RhostsRSAAuthentication +Specifies whether rhosts or +.Pa /etc/hosts.equiv +authentication together +with successful RSA host authentication is allowed. +The default is +.Dq no . +This option applies to protocol version 1 only. +.It Cm RSAAuthentication +Specifies whether pure RSA authentication is allowed. +The default is +.Dq yes . +This option applies to protocol version 1 only. +.It Cm ServerKeyBits +Defines the number of bits in the ephemeral protocol version 1 server key. +The minimum value is 512, and the default is 768. +.It Cm StrictModes +Specifies whether +.Nm sshd +should check file modes and ownership of the +user's files and home directory before accepting login. +This is normally desirable because novices sometimes accidentally leave their +directory or files world-writable. +The default is +.Dq yes . +.It Cm Subsystem +Configures an external subsystem (e.g., file transfer daemon). +Arguments should be a subsystem name and a command to execute upon subsystem +request. +The command +.Xr sftp-server 8 +implements the +.Dq sftp +file transfer subsystem. +By default no subsystems are defined. +Note that this option applies to protocol version 2 only. +.It Cm SyslogFacility +Gives the facility code that is used when logging messages from +.Nm sshd . +The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, +LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. +The default is AUTH. +.It Cm UseLogin +Specifies whether +.Xr login 1 +is used for interactive login sessions. +The default is +.Dq no . +Note that +.Xr login 1 +is never used for remote command execution. +Note also, that if this is enabled, +.Cm X11Forwarding +will be disabled because +.Xr login 1 +does not know how to handle +.Xr xauth 1 +cookies. If +.Cm UsePrivilegeSeparation +is specified, it will be disabled after authentication. +.It Cm UsePrivilegeSeparation +Specifies whether +.Nm sshd +separates privileges by creating an unprivileged child process +to deal with incoming network traffic. After successful authentication, +another process will be created that has the privilege of the authenticated +user. The goal of privilege separation is to prevent privilege +escalation by containing any corruption within the unprivileged processes. +The default is +.Dq yes . +.It Cm VerifyReverseMapping +Specifies whether +.Nm sshd +should try to verify the remote host name and check that +the resolved host name for the remote IP address maps back to the +very same IP address. +The default is +.Dq no . +.It Cm VersionAddendum +Specifies a string to append to the regular version string to identify +OS- or site-specific modifications. +.It Cm X11DisplayOffset +Specifies the first display number available for +.Nm sshd Ns 's +X11 forwarding. +This prevents +.Nm sshd +from interfering with real X11 servers. +The default is 10. +.It Cm X11Forwarding +Specifies whether X11 forwarding is permitted. +The default is +.Dq no . +Note that disabling X11 forwarding does not improve security in any +way, as users can always install their own forwarders. +X11 forwarding is automatically disabled if +.Cm UseLogin +is enabled. +.It Cm X11UseLocalhost +Specifies whether +.Nm sshd +should bind the X11 forwarding server to the loopback address or to +the wildcard address. By default, +.Nm sshd +binds the forwarding server to the loopback address and sets the +hostname part of the +.Ev DISPLAY +environment variable to +.Dq localhost . +This prevents remote hosts from connecting to the fake display. +However, some older X11 clients may not function with this +configuration. +.Cm X11UseLocalhost +may be set to +.Dq no +to specify that the forwarding server should be bound to the wildcard +address. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq yes . +.It Cm XAuthLocation +Specifies the location of the +.Xr xauth 1 +program. +The default is +.Pa /usr/X11R6/bin/xauth . +.El +.Ss Time Formats +.Pp +.Nm sshd +command-line arguments and configuration file options that specify time +may be expressed using a sequence of the form: +.Sm off +.Ar time Oo Ar qualifier Oc , +.Sm on +where +.Ar time +is a positive integer value and +.Ar qualifier +is one of the following: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Cm +seconds +.It Cm s | Cm S +seconds +.It Cm m | Cm M +minutes +.It Cm h | Cm H +hours +.It Cm d | Cm D +days +.It Cm w | Cm W +weeks +.El +.Pp +Each member of the sequence is added together to calculate +the total time value. +.Pp +Time format examples: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It 600 +600 seconds (10 minutes) +.It 10m +10 minutes +.It 1h30m +1 hour 30 minutes (90 minutes) +.El +.Sh FILES +.Bl -tag -width Ds +.It Pa /etc/ssh/sshd_config +Contains configuration data for +.Nm sshd . +This file should be writable by root only, but it is recommended +(though not necessary) that it be world-readable. +.El +.Sh AUTHORS +OpenSSH is a derivative of the original and free +ssh 1.2.12 release by Tatu Ylonen. +Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, +Theo de Raadt and Dug Song +removed many bugs, re-added newer features and +created OpenSSH. +Markus Friedl contributed the support for SSH +protocol versions 1.5 and 2.0. +Niels Provos and Markus Friedl contributed support +for privilege separation. +.Sh SEE ALSO +.Xr sshd 8 Index: src/crypto/openssh/sshlogin.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshlogin.c,v retrieving revision 1.3.2.1 diff -u -u -r1.3.2.1 sshlogin.c --- src/crypto/openssh/sshlogin.c 28 Sep 2001 01:33:35 -0000 1.3.2.1 +++ src/crypto/openssh/sshlogin.c 30 Jun 2002 11:38:02 -0000 @@ -39,99 +39,64 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshlogin.c,v 1.2 2001/03/24 16:43:27 stevesk Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/sshlogin.c,v 1.3.2.1 2001/09/28 01:33:35 green Exp $"); +RCSID("$OpenBSD: sshlogin.c,v 1.4 2002/06/23 03:30:17 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/sshlogin.c,v 1.6 2002/06/29 11:48:59 des Exp $"); -#include -#include -#include "sshlogin.h" -#include "log.h" +#include "loginrec.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. */ - u_long get_last_login_time(uid_t uid, const char *logname, - char *buf, u_int bufsize) + char *buf, u_int bufsize) { - struct lastlog ll; - char *lastlog; - int fd; - - lastlog = _PATH_LASTLOG; - buf[0] = '\0'; - - fd = open(lastlog, O_RDONLY); - if (fd < 0) - return 0; - lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET); - 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; + struct logininfo li; + + login_get_lastlog(&li, uid); + strlcpy(buf, li.hostname, bufsize); + return li.tv_sec; } /* * Records that the user has logged in. I these parts of operating systems * were more standardized. */ - void record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid, - const char *host, struct sockaddr * addr) + const char *host, struct sockaddr * addr) { - int fd; - struct lastlog ll; - char *lastlog; - struct utmp u; - - /* Construct an utmp/wtmp entry. */ - memset(&u, 0, sizeof(u)); - strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line)); - u.ut_time = time(NULL); - strncpy(u.ut_name, user, sizeof(u.ut_name)); - realhostname_sa(u.ut_host, sizeof(u.ut_host), addr, addr->sa_len); - - login(&u); - lastlog = _PATH_LASTLOG; - - /* 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)); - fd = open(lastlog, O_RDWR); - if (fd >= 0) { - lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET); - if (write(fd, &ll, sizeof(ll)) != sizeof(ll)) - log("Could not write %.100s: %.100s", lastlog, strerror(errno)); - close(fd); - } - } + struct logininfo *li; + + li = login_alloc_entry(pid, user, host, ttyname); + login_set_addr(li, addr, sizeof(struct sockaddr)); + login_login(li); + login_free_entry(li); } -/* Records that the user has logged out. */ +#ifdef LOGIN_NEEDS_UTMPX +void +record_utmp_only(pid_t pid, const char *ttyname, const char *user, + const char *host, struct sockaddr * addr) +{ + struct logininfo *li; + + li = login_alloc_entry(pid, user, host, ttyname); + login_set_addr(li, addr, sizeof(struct sockaddr)); + login_utmp_only(li); + login_free_entry(li); +} +#endif +/* Records that the user has logged out. */ void -record_logout(pid_t pid, const char *ttyname) +record_logout(pid_t pid, const char *ttyname, const char *user) { - const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */ - if (logout(line)) - logwtmp(line, "", ""); + struct logininfo *li; + + li = login_alloc_entry(pid, user, NULL, ttyname); + login_logout(li); + login_free_entry(li); } Index: src/crypto/openssh/sshlogin.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshlogin.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sshlogin.h --- src/crypto/openssh/sshlogin.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sshlogin.h 30 Jun 2002 11:38:02 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshlogin.h,v 1.1 2001/03/04 01:46:30 djm Exp $ */ +/* $OpenBSD: sshlogin.h,v 1.3 2001/06/26 17:27:25 markus Exp $ */ /* * Author: Tatu Ylonen @@ -14,27 +14,15 @@ #ifndef SSHLOGIN_H #define SSHLOGIN_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 from which the user logged in is stored in buf. - */ -u_long -get_last_login_time(uid_t uid, const char *logname, - char *buf, u_int bufsize); - -/* - * Records that the user has logged in. This does many things normally done - * by login(1). - */ void -record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid, - const char *host, struct sockaddr *addr); +record_login(pid_t, const char *, const char *, uid_t, + const char *, struct sockaddr *); +void record_logout(pid_t, const char *, const char *); +u_long get_last_login_time(uid_t, const char *, char *, u_int); -/* - * Records that the user has logged out. This does many thigs normally done - * by login(1) or init. - */ -void record_logout(pid_t pid, const char *ttyname); +#ifdef LOGIN_NEEDS_UTMPX +void record_utmp_only(pid_t, const char *, const char *, const char *, + struct sockaddr *); +#endif #endif Index: src/crypto/openssh/sshpty.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshpty.c,v retrieving revision 1.2.2.1 diff -u -u -r1.2.2.1 sshpty.c --- src/crypto/openssh/sshpty.c 28 Sep 2001 01:33:35 -0000 1.2.2.1 +++ src/crypto/openssh/sshpty.c 30 Jun 2002 11:38:02 -0000 @@ -12,18 +12,29 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshpty.c,v 1.1 2001/03/04 01:46:30 djm Exp $"); -RCSID("$FreeBSD: src/crypto/openssh/sshpty.c,v 1.2.2.1 2001/09/28 01:33:35 green Exp $"); +RCSID("$OpenBSD: sshpty.c,v 1.7 2002/06/24 17:57:20 deraadt Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/sshpty.c,v 1.5 2002/06/29 11:48:59 des Exp $"); + +#ifdef HAVE_UTIL_H +# include +#endif /* HAVE_UTIL_H */ -#include #include "sshpty.h" #include "log.h" +#include "misc.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_PTY_H +# include +#endif +#if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) +# include +#endif + #ifndef O_NOCTTY #define O_NOCTTY 0 #endif @@ -40,15 +51,19 @@ { #if defined(HAVE_OPENPTY) || defined(BSD4_4) /* openpty(3) exists in OSF/1 and some other os'es */ - char buf[64]; + char *name; int i; - i = openpty(ptyfd, ttyfd, buf, NULL, NULL); + i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); if (i < 0) { error("openpty: %.100s", strerror(errno)); return 0; } - strlcpy(namebuf, buf, namebuflen); /* possible truncation */ + name = ttyname(*ttyfd); + if (!name) + fatal("openpty returns device for which ttyname fails."); + + strlcpy(namebuf, name, namebuflen); /* possible truncation */ return 1; #else /* HAVE_OPENPTY */ #ifdef HAVE__GETPTY @@ -73,23 +88,26 @@ } return 1; #else /* HAVE__GETPTY */ -#ifdef HAVE_DEV_PTMX +#if defined(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; + mysig_t old_signal; ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); if (ptm < 0) { error("/dev/ptmx: %.100s", strerror(errno)); return 0; } + old_signal = mysignal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) { error("grantpt: %.100s", strerror(errno)); return 0; } + mysignal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) { error("unlockpt: %.100s", strerror(errno)); return 0; @@ -107,13 +125,20 @@ close(*ptyfd); return 0; } - /* Push the appropriate streams modules, as described in Solaris pts(7). */ +#ifndef HAVE_CYGWIN + /* + * Push the appropriate streams modules, as described in Solaris pts(7). + * HP-UX pts(7) doesn't have ttcompat module. + */ 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)); +#ifndef __hpux if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) error("ioctl I_PUSH ttcompat: %.100s", strerror(errno)); +#endif +#endif return 1; #else /* HAVE_DEV_PTMX */ #ifdef HAVE_DEV_PTS_AND_PTC @@ -132,12 +157,42 @@ *ttyfd = open(name, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { error("Could not open pty slave side %.100s: %.100s", - name, strerror(errno)); + name, strerror(errno)); close(*ptyfd); return 0; } return 1; #else /* HAVE_DEV_PTS_AND_PTC */ +#ifdef _CRAY + char buf[64]; + int i; + int highpty; + +#ifdef _SC_CRAY_NPTY + highpty = sysconf(_SC_CRAY_NPTY); + if (highpty == -1) + highpty = 128; +#else + highpty = 128; +#endif + + for (i = 0; i < highpty; i++) { + snprintf(buf, sizeof(buf), "/dev/pty/%03d", i); + *ptyfd = open(buf, O_RDWR|O_NOCTTY); + if (*ptyfd < 0) + continue; + snprintf(namebuf, namebuflen, "/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 /* BSD-style pty code. */ char buf[64]; int i; @@ -145,16 +200,24 @@ const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; + struct termios tio; for (i = 0; i < num_ptys; i++) { snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); - *ptyfd = open(buf, O_RDWR | O_NOCTTY); - if (*ptyfd < 0) - continue; snprintf(namebuf, namebuflen, "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); + *ptyfd = open(buf, O_RDWR | O_NOCTTY); + if (*ptyfd < 0) { + /* Try SCO style naming */ + snprintf(buf, sizeof buf, "/dev/ptyp%d", i); + snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); + *ptyfd = open(buf, O_RDWR | O_NOCTTY); + if (*ptyfd < 0) + continue; + } + /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { @@ -162,9 +225,23 @@ close(*ptyfd); return 0; } + /* set tty modes to a sane state for broken clients */ + if (tcgetattr(*ptyfd, &tio) < 0) + log("Getting tty modes for pty failed: %.100s", strerror(errno)); + else { + tio.c_lflag |= (ECHO | ISIG | ICANON); + tio.c_oflag |= (OPOST | ONLCR); + tio.c_iflag |= ICRNL; + + /* Set the new modes for the terminal. */ + if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) + log("Setting tty modes for pty failed: %.100s", strerror(errno)); + } + return 1; } return 0; +#endif /* CRAY */ #endif /* HAVE_DEV_PTS_AND_PTC */ #endif /* HAVE_DEV_PTMX */ #endif /* HAVE__GETPTY */ @@ -188,6 +265,33 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname) { int fd; +#ifdef USE_VHANGUP + void *old; +#endif /* USE_VHANGUP */ + +#ifdef _CRAY + if (setsid() < 0) + error("setsid: %.100s", strerror(errno)); + + fd = open(ttyname, O_RDWR|O_NOCTTY); + if (fd != -1) { + mysignal(SIGHUP, SIG_IGN); + ioctl(fd, TCVHUP, (char *)NULL); + mysignal(SIGHUP, SIG_DFL); + setpgid(0, 0); + close(fd); + } else { + error("Failed to disconnect from controlling tty."); + } + + debug("Setting controlling tty using TCSETCTTY."); + ioctl(*ttyfd, TCSETCTTY, NULL); + fd = open("/dev/tty", O_RDWR); + if (fd < 0) + error("%.100s: %.100s", ttyname, strerror(errno)); + close(*ttyfd); + *ttyfd = fd; +#else /* _CRAY */ /* First disconnect from the old controlling tty. */ #ifdef TIOCNOTTY @@ -215,29 +319,44 @@ if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); #endif /* TIOCSCTTY */ +#ifdef HAVE_NEWS4 + if (setpgrp(0,0) < 0) + error("SETPGRP %s",strerror(errno)); +#endif /* HAVE_NEWS4 */ +#ifdef USE_VHANGUP + old = mysignal(SIGHUP, SIG_IGN); + vhangup(); + mysignal(SIGHUP, old); +#endif /* USE_VHANGUP */ fd = open(ttyname, O_RDWR); - if (fd < 0) + if (fd < 0) { error("%.100s: %.100s", ttyname, strerror(errno)); - else + } else { +#ifdef USE_VHANGUP + close(*ttyfd); + *ttyfd = fd; +#else /* USE_VHANGUP */ close(fd); - +#endif /* USE_VHANGUP */ + } /* Verify that we now have a controlling tty. */ fd = open(_PATH_TTY, O_WRONLY); if (fd < 0) error("open /dev/tty failed - could not set controlling tty: %.100s", - strerror(errno)); - else { + strerror(errno)); + else close(fd); - } +#endif /* _CRAY */ } /* Changes the window size associated with the pty. */ void pty_change_window_size(int ptyfd, int row, int col, - int xpixel, int ypixel) + int xpixel, int ypixel) { struct winsize w; + w.ws_row = row; w.ws_col = col; w.ws_xpixel = xpixel; @@ -265,7 +384,8 @@ /* * Change owner and mode of the tty as required. - * Warn but continue if filesystem is read-only and the uids match. + * Warn but continue if filesystem is read-only and the uids match/ + * tty is owned by root. */ if (stat(ttyname, &st)) fatal("stat(%.100s) failed: %.100s", ttyname, @@ -273,14 +393,15 @@ if (st.st_uid != pw->pw_uid || st.st_gid != gid) { if (chown(ttyname, pw->pw_uid, gid) < 0) { - if (errno == EROFS && st.st_uid == pw->pw_uid) - error("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); + if (errno == EROFS && + (st.st_uid == pw->pw_uid || st.st_uid == 0)) + error("chown(%.100s, %u, %u) failed: %.100s", + ttyname, (u_int)pw->pw_uid, (u_int)gid, + strerror(errno)); else - fatal("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); + fatal("chown(%.100s, %u, %u) failed: %.100s", + ttyname, (u_int)pw->pw_uid, (u_int)gid, + strerror(errno)); } } @@ -289,10 +410,10 @@ if (errno == EROFS && (st.st_mode & (S_IRGRP | S_IROTH)) == 0) error("chmod(%.100s, 0%o) failed: %.100s", - ttyname, mode, strerror(errno)); + ttyname, mode, strerror(errno)); else fatal("chmod(%.100s, 0%o) failed: %.100s", - ttyname, mode, strerror(errno)); + ttyname, mode, strerror(errno)); } } } Index: src/crypto/openssh/sshpty.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshpty.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sshpty.h --- src/crypto/openssh/sshpty.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sshpty.h 30 Jun 2002 11:38:02 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: sshpty.h,v 1.4 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,36 +14,13 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: sshpty.h,v 1.1 2001/03/04 01:46:30 djm Exp $"); */ - #ifndef SSHPTY_H #define SSHPTY_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, int ttynamelen); - -/* - * 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); - -void pty_setowner(struct passwd *pw, const char *ttyname); +int pty_allocate(int *, int *, char *, int); +void pty_release(const char *); +void pty_make_controlling_tty(int *, const char *); +void pty_change_window_size(int, int, int, int, int); +void pty_setowner(struct passwd *, const char *); #endif /* SSHPTY_H */ Index: src/crypto/openssh/sshtty.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshtty.c,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sshtty.c --- src/crypto/openssh/sshtty.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sshtty.c 30 Jun 2002 11:38:02 -0000 @@ -1,4 +1,3 @@ -/* $OpenBSD: sshtty.c,v 1.1 2001/04/14 16:33:20 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -36,6 +35,7 @@ */ #include "includes.h" +RCSID("$OpenBSD: sshtty.c,v 1.3 2002/03/04 17:27:39 stevesk Exp $"); #include "sshtty.h" #include "log.h" @@ -46,7 +46,7 @@ int in_raw_mode(void) { - return _in_raw_mode; + return _in_raw_mode; } struct termios Index: src/crypto/openssh/sshtty.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/sshtty.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 sshtty.h --- src/crypto/openssh/sshtty.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/sshtty.h 30 Jun 2002 11:38:02 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshtty.h,v 1.1 2001/04/14 16:33:20 stevesk Exp $ */ +/* $OpenBSD: sshtty.h,v 1.2 2001/06/26 17:27:25 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -40,26 +40,9 @@ #include -/* - * Accessor function indicating whether we are in raw mode. Set by - * enter_raw_mode() and leave_raw_mode(). - */ -int in_raw_mode(void); - -/* - * Return terminal modes, as saved by enter_raw_mode(). - */ +int in_raw_mode(void); struct termios get_saved_tio(void); - -/* - * Returns the user's terminal to normal mode if it had been - * put in raw mode. - */ -void leave_raw_mode(void); - -/* - * Puts the user's terminal in raw mode. - */ -void enter_raw_mode(void); +void leave_raw_mode(void); +void enter_raw_mode(void); #endif Index: src/crypto/openssh/tildexpand.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/tildexpand.c,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 tildexpand.c --- src/crypto/openssh/tildexpand.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/tildexpand.c 30 Jun 2002 11:38:02 -0000 @@ -11,7 +11,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: tildexpand.c,v 1.11 2001/02/08 19:30:53 itojun Exp $"); +RCSID("$OpenBSD: tildexpand.c,v 1.13 2002/06/23 03:25:50 deraadt Exp $"); #include "xmalloc.h" #include "log.h" @@ -67,6 +67,7 @@ if (len > MAXPATHLEN) fatal("Home directory too long (%d > %d", len-1, MAXPATHLEN-1); expanded = xmalloc(len); - snprintf(expanded, len, "%s/%s", pw->pw_dir, cp + 1); + snprintf(expanded, len, "%s%s%s", pw->pw_dir, + strcmp(pw->pw_dir, "/") ? "/" : "", cp + 1); return expanded; } Index: src/crypto/openssh/tildexpand.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/tildexpand.h,v retrieving revision 1.1.1.1.2.1 diff -u -u -r1.1.1.1.2.1 tildexpand.h --- src/crypto/openssh/tildexpand.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.1 +++ src/crypto/openssh/tildexpand.h 30 Jun 2002 11:38:02 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: tildexpand.h,v 1.2 2001/01/29 01:58:19 niklas Exp $ */ +/* $OpenBSD: tildexpand.h,v 1.4 2001/06/26 17:27:25 markus Exp $ */ /* * Author: Tatu Ylonen @@ -12,8 +12,4 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* - * 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); +char *tilde_expand_filename(const char *, uid_t); Index: src/crypto/openssh/ttymodes.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ttymodes.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 ttymodes.c --- src/crypto/openssh/ttymodes.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/ttymodes.c 30 Jun 2002 11:38:02 -0000 @@ -43,7 +43,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ttymodes.c,v 1.13 2001/04/15 01:35:22 stevesk Exp $"); +RCSID("$OpenBSD: ttymodes.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $"); #include "packet.h" #include "log.h" @@ -275,22 +275,22 @@ /* Store input and output baud rates. */ baud = speed_to_baud(cfgetospeed(&tio)); - debug2("tty_make_modes: ospeed %d", baud); + debug3("tty_make_modes: ospeed %d", baud); buffer_put_char(&buf, tty_op_ospeed); buffer_put_int(&buf, baud); baud = speed_to_baud(cfgetispeed(&tio)); - debug2("tty_make_modes: ispeed %d", baud); + debug3("tty_make_modes: ispeed %d", baud); buffer_put_char(&buf, tty_op_ispeed); buffer_put_int(&buf, baud); /* Store values of mode flags. */ #define TTYCHAR(NAME, OP) \ - debug2("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \ + debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \ buffer_put_char(&buf, OP); \ put_arg(&buf, tio.c_cc[NAME]); #define TTYMODE(NAME, FIELD, OP) \ - debug2("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \ + debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \ buffer_put_char(&buf, OP); \ put_arg(&buf, ((tio.FIELD & NAME) != 0)); @@ -307,7 +307,6 @@ else packet_put_raw(buffer_ptr(&buf), buffer_len(&buf)); buffer_free(&buf); - return; } /* @@ -326,7 +325,7 @@ if (compat20) { *n_bytes_ptr = packet_get_int(); - debug2("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); + debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); if (*n_bytes_ptr == 0) return; get_arg = packet_get_int; @@ -358,7 +357,7 @@ case TTY_OP_ISPEED_PROTO2: n_bytes += 4; baud = packet_get_int(); - debug2("tty_parse_modes: ispeed %d", baud); + debug3("tty_parse_modes: ispeed %d", baud); if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) error("cfsetispeed failed for %d", baud); break; @@ -368,7 +367,7 @@ case TTY_OP_OSPEED_PROTO2: n_bytes += 4; baud = packet_get_int(); - debug2("tty_parse_modes: ospeed %d", baud); + debug3("tty_parse_modes: ospeed %d", baud); if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) error("cfsetospeed failed for %d", baud); break; @@ -377,7 +376,7 @@ case OP: \ n_bytes += arg_size; \ tio.c_cc[NAME] = get_arg(); \ - debug2("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \ + debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \ break; #define TTYMODE(NAME, FIELD, OP) \ case OP: \ @@ -386,7 +385,7 @@ tio.FIELD |= NAME; \ else \ tio.FIELD &= ~NAME; \ - debug2("tty_parse_modes: %d %d", OP, arg); \ + debug3("tty_parse_modes: %d %d", OP, arg); \ break; #include "ttymodes.h" @@ -396,23 +395,23 @@ default: debug("Ignoring unsupported tty mode opcode %d (0x%x)", - opcode, opcode); + opcode, opcode); if (!compat20) { /* * SSH1: * Opcodes 1 to 127 are defined to have * a one-byte argument. - * Opcodes 128 to 159 are defined to have - * an integer argument. - */ + * Opcodes 128 to 159 are defined to have + * an integer argument. + */ if (opcode > 0 && opcode < 128) { n_bytes += 1; (void) packet_get_char(); break; } else if (opcode >= 128 && opcode < 160) { - n_bytes += 4; - (void) packet_get_int(); - break; + n_bytes += 4; + (void) packet_get_int(); + break; } else { /* * It is a truly undefined opcode (160 to 255). @@ -422,9 +421,8 @@ * 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; - } + } } else { /* * SSH2: @@ -441,7 +439,7 @@ log("parse_tty_modes: unknown opcode %d", opcode); goto set; } - } + } } } @@ -458,5 +456,4 @@ /* Set the new modes for the terminal. */ if (tcsetattr(fd, TCSANOW, &tio) == -1) log("Setting tty modes failed: %.100s", strerror(errno)); - return; } Index: src/crypto/openssh/ttymodes.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/ttymodes.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 ttymodes.h --- src/crypto/openssh/ttymodes.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/ttymodes.h 30 Jun 2002 11:38:02 -0000 @@ -1,4 +1,5 @@ -/* RCSID("$OpenBSD: ttymodes.h,v 1.11 2001/04/14 16:33:20 stevesk Exp $"); */ +/* $OpenBSD: ttymodes.h,v 1.12 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -155,7 +156,9 @@ #if defined(OLCUC) TTYMODE(OLCUC, c_oflag, 71) #endif +#ifdef ONLCR TTYMODE(ONLCR, c_oflag, 72) +#endif #ifdef OCRNL TTYMODE(OCRNL, c_oflag, 73) #endif Index: src/crypto/openssh/uidswap.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/uidswap.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 uidswap.c --- src/crypto/openssh/uidswap.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/uidswap.c 30 Jun 2002 11:38:02 -0000 @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: uidswap.c,v 1.16 2001/04/20 16:32:22 markus Exp $"); +RCSID("$OpenBSD: uidswap.c,v 1.22 2002/05/28 21:24:00 stevesk Exp $"); #include "log.h" #include "uidswap.h" @@ -26,14 +26,18 @@ * POSIX saved uids or not. */ +#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS) /* 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 +/* Saved effective uid. */ +static uid_t saved_euid = 0; +static gid_t saved_egid = 0; +#endif /* Saved effective uid. */ static int privileged = 0; static int temporarily_use_uid_effective = 0; -static uid_t saved_euid = 0; -static gid_t saved_egid; static gid_t saved_egroups[NGROUPS_MAX], user_groups[NGROUPS_MAX]; static int saved_egroupslen = -1, user_groupslen = -1; @@ -45,17 +49,25 @@ temporarily_use_uid(struct passwd *pw) { /* Save the current euid, and egroups. */ +#ifdef SAVED_IDS_WORK_WITH_SETEUID saved_euid = geteuid(); - debug("temporarily_use_uid: %d/%d (e=%d)", - pw->pw_uid, pw->pw_gid, saved_euid); + saved_egid = getegid(); + debug("temporarily_use_uid: %u/%u (e=%u)", + (u_int)pw->pw_uid, (u_int)pw->pw_gid, (u_int)saved_euid); if (saved_euid != 0) { privileged = 0; return; } +#else + if (geteuid() != 0) { + privileged = 0; + return; + } +#endif /* SAVED_IDS_WORK_WITH_SETEUID */ + privileged = 1; temporarily_use_uid_effective = 1; - saved_egid = getegid(); - saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups); + saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups); if (saved_egroupslen < 0) fatal("getgroups: %.100s", strerror(errno)); @@ -64,19 +76,26 @@ if (initgroups(pw->pw_name, pw->pw_gid) < 0) fatal("initgroups: %s: %.100s", pw->pw_name, strerror(errno)); - user_groupslen = getgroups(NGROUPS_MAX, user_groups); + user_groupslen = getgroups(NGROUPS_MAX, user_groups); if (user_groupslen < 0) fatal("getgroups: %.100s", strerror(errno)); } /* Set the effective uid to the given (unprivileged) uid. */ if (setgroups(user_groupslen, user_groups) < 0) fatal("setgroups: %.100s", strerror(errno)); - pw->pw_gid = pw->pw_gid; +#ifndef SAVED_IDS_WORK_WITH_SETEUID + /* Propagate the privileged gid to all of our gids. */ + if (setgid(getegid()) < 0) + debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno)); + /* Propagate the privileged uid to all of our uids. */ + if (setuid(geteuid()) < 0) + debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno)); +#endif /* SAVED_IDS_WORK_WITH_SETEUID */ if (setegid(pw->pw_gid) < 0) - fatal("setegid %u: %.100s", (u_int) pw->pw_gid, + fatal("setegid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); if (seteuid(pw->pw_uid) == -1) - fatal("seteuid %u: %.100s", (u_int) pw->pw_uid, + fatal("seteuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); } @@ -92,13 +111,25 @@ return; if (!temporarily_use_uid_effective) fatal("restore_uid: temporarily_use_uid not effective"); + +#ifdef SAVED_IDS_WORK_WITH_SETEUID /* Set the effective uid back to the saved privileged uid. */ if (seteuid(saved_euid) < 0) - fatal("seteuid %u: %.100s", (u_int) saved_euid, strerror(errno)); + fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno)); + if (setegid(saved_egid) < 0) + fatal("setegid %u: %.100s", (u_int)saved_egid, 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()); + setgid(getgid()); +#endif /* SAVED_IDS_WORK_WITH_SETEUID */ + if (setgroups(saved_egroupslen, saved_egroups) < 0) fatal("setgroups: %.100s", strerror(errno)); - if (setegid(saved_egid) < 0) - fatal("setegid %u: %.100s", (u_int) saved_egid, strerror(errno)); temporarily_use_uid_effective = 0; } @@ -110,9 +141,9 @@ permanently_set_uid(struct passwd *pw) { if (temporarily_use_uid_effective) - fatal("restore_uid: temporarily_use_uid effective"); + fatal("permanently_set_uid: temporarily_use_uid effective"); if (setgid(pw->pw_gid) < 0) - fatal("setgid %u: %.100s", (u_int) pw->pw_gid, strerror(errno)); + fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); if (setuid(pw->pw_uid) < 0) - fatal("setuid %u: %.100s", (u_int) pw->pw_uid, strerror(errno)); + fatal("setuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); } Index: src/crypto/openssh/uidswap.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/uidswap.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 uidswap.h --- src/crypto/openssh/uidswap.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/uidswap.h 30 Jun 2002 11:38:02 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: uidswap.h,v 1.7 2001/04/06 21:00:17 markus Exp $ */ +/* $OpenBSD: uidswap.h,v 1.9 2001/06/26 17:27:25 markus Exp $ */ /* * Author: Tatu Ylonen @@ -15,22 +15,8 @@ #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(struct passwd *pw); - -/* - * Restores the original effective user id after temporarily_use_uid(). - * This should only be called while temporarily_use_uid is effective. - */ -void restore_uid(void); - -/* - * 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(struct passwd *pw); +void temporarily_use_uid(struct passwd *); +void restore_uid(void); +void permanently_set_uid(struct passwd *); #endif /* UIDSWAP_H */ Index: src/crypto/openssh/uuencode.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/uuencode.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 uuencode.c --- src/crypto/openssh/uuencode.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/uuencode.c 30 Jun 2002 11:38:02 -0000 @@ -1,5 +1,3 @@ -/* $OpenBSD: uuencode.c,v 1.12 2001/03/01 02:27:18 deraadt Exp $ */ - /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -27,10 +25,7 @@ #include "includes.h" #include "xmalloc.h" #include "uuencode.h" - -#include - -RCSID("$OpenBSD: uuencode.c,v 1.12 2001/03/01 02:27:18 deraadt Exp $"); +RCSID("$OpenBSD: uuencode.c,v 1.15 2002/03/04 17:27:39 stevesk Exp $"); int uuencode(u_char *src, u_int srclength, @@ -52,7 +47,7 @@ ; for (; *p != '\0' && *p != ' ' && *p != '\t'; p++) ; - /* and remote trailing whitespace because __b64_pton needs this */ + /* and remove trailing whitespace because __b64_pton needs this */ *p = '\0'; len = __b64_pton(encoded, target, targsize); xfree(encoded); @@ -60,7 +55,7 @@ } void -dump_base64(FILE *fp, u_char *data, int len) +dump_base64(FILE *fp, u_char *data, u_int len) { u_char *buf = xmalloc(2*len); int i, n; Index: src/crypto/openssh/uuencode.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/uuencode.h,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 uuencode.h --- src/crypto/openssh/uuencode.h 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/uuencode.h 30 Jun 2002 11:38:02 -0000 @@ -1,7 +1,7 @@ -/* $OpenBSD: uuencode.h,v 1.5 2001/01/29 01:58:19 niklas Exp $ */ +/* $OpenBSD: uuencode.h,v 1.9 2002/02/25 16:33:27 markus Exp $ */ /* - * Copyright (c) 1999 Markus Friedl. All rights reserved. + * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,7 @@ #ifndef UUENCODE_H #define UUENCODE_H -int uuencode(u_char *src, u_int srclength, char *target, size_t targsize); -int uudecode(const char *src, u_char *target, size_t targsize); -void dump_base64(FILE *fp, u_char *data, int len); +int uuencode(u_char *, u_int, char *, size_t); +int uudecode(const char *, u_char *, size_t); +void dump_base64(FILE *, u_char *, u_int); #endif Index: src/crypto/openssh/version.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/version.c,v retrieving revision 1.1.2.1 diff -u -u -r1.1.2.1 version.c --- src/crypto/openssh/version.c 28 Sep 2001 01:33:35 -0000 1.1.2.1 +++ src/crypto/openssh/version.c 30 Jun 2002 11:38:02 -0000 @@ -29,7 +29,7 @@ #include "version.h" #include "xmalloc.h" -RCSID("$FreeBSD: src/crypto/openssh/version.c,v 1.1.2.1 2001/09/28 01:33:35 green Exp $"); +RCSID("$FreeBSD: src/crypto/openssh/version.c,v 1.3 2002/06/29 10:52:42 des Exp $"); static char *version = NULL; Index: src/crypto/openssh/version.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/version.h,v retrieving revision 1.1.1.1.2.8 diff -u -u -r1.1.1.1.2.8 version.h --- src/crypto/openssh/version.h 7 Mar 2002 14:36:26 -0000 1.1.1.1.2.8 +++ src/crypto/openssh/version.h 30 Jun 2002 11:38:02 -0000 @@ -1,12 +1,13 @@ -/* $FreeBSD: src/crypto/openssh/version.h,v 1.1.1.1.2.8 2002/03/07 14:36:26 nectar Exp $ */ -/* $OpenBSD: version.h,v 1.23 2001/04/24 16:43:16 markus Exp $ */ +/* $OpenBSD: version.h,v 1.34 2002/06/26 13:56:27 markus Exp $ */ +/* $FreeBSD: src/crypto/openssh/version.h,v 1.16 2002/06/29 11:48:59 des Exp $ */ -#ifndef SSH_VERSION +#ifndef SSH_VERSION -#define SSH_VERSION (ssh_version_get()) -#define SSH_VERSION_BASE "OpenSSH_2.9" -#define SSH_VERSION_ADDENDUM "FreeBSD localisations 20020307" +#define SSH_VERSION (ssh_version_get()) +#define SSH_VERSION_BASE "OpenSSH_3.4p1" +#define SSH_VERSION_ADDENDUM "FreeBSD-20020629" const char *ssh_version_get(void); void ssh_version_set_addendum(const char *add); #endif /* SSH_VERSION */ + Index: src/crypto/openssh/xmalloc.c =================================================================== RCS file: /home/ncvs/src/crypto/openssh/xmalloc.c,v retrieving revision 1.1.1.1.2.3 diff -u -u -r1.1.1.1.2.3 xmalloc.c --- src/crypto/openssh/xmalloc.c 28 Sep 2001 01:33:35 -0000 1.1.1.1.2.3 +++ src/crypto/openssh/xmalloc.c 30 Jun 2002 11:38:02 -0000 @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: xmalloc.c,v 1.15 2001/04/16 08:05:34 deraadt Exp $"); +RCSID("$OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp $"); #include "xmalloc.h" #include "log.h" @@ -58,11 +58,10 @@ char * xstrdup(const char *str) { - size_t len = strlen(str) + 1; + size_t len; char *cp; - if (len == 0) - fatal("xstrdup: zero size"); + len = strlen(str) + 1; cp = xmalloc(len); strlcpy(cp, str, len); return cp; Index: src/crypto/openssh/xmalloc.h =================================================================== RCS file: /home/ncvs/src/crypto/openssh/xmalloc.h,v retrieving revision 1.1.1.1.2.2 diff -u -u -r1.1.1.1.2.2 xmalloc.h --- src/crypto/openssh/xmalloc.h 28 Oct 2000 23:00:51 -0000 1.1.1.1.2.2 +++ src/crypto/openssh/xmalloc.h 30 Jun 2002 11:38:02 -0000 @@ -1,3 +1,5 @@ +/* $OpenBSD: xmalloc.h,v 1.9 2002/06/19 00:27:55 deraadt Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -14,21 +16,12 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: xmalloc.h,v 1.5 2000/09/07 20:27:56 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); +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +void xfree(void *); +char *xstrdup(const char *); #endif /* XMALLOC_H */ Index: src/crypto/openssh/lib/Makefile =================================================================== RCS file: src/crypto/openssh/lib/Makefile diff -N src/crypto/openssh/lib/Makefile --- src/crypto/openssh/lib/Makefile 28 Sep 2001 01:33:49 -0000 1.1.1.1.2.4 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,29 +0,0 @@ -# $OpenBSD: Makefile,v 1.22 2001/04/03 19:53:30 markus Exp $ - -.PATH: ${.CURDIR}/.. - -LIB= ssh -SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \ - cipher.c compat.c compress.c crc32.c deattack.c \ - hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \ - rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \ - key.c dispatch.c kex.c mac.c uuencode.c misc.c \ - cli.c rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c - -NOPROFILE= yes -NOPIC= yes - -install: - @echo -n - -.include - -.if (${KERBEROS:L} == "yes") -CFLAGS+= -DKRB4 -I${DESTDIR}/usr/include/kerberosIV -.if (${AFS:L} == "yes") -CFLAGS+= -DAFS -SRCS+= radix.c -.endif # AFS -.endif # KERBEROS - -.include Index: src/crypto/openssh/openbsd-compat/Makefile.in =================================================================== RCS file: src/crypto/openssh/openbsd-compat/Makefile.in diff -N src/crypto/openssh/openbsd-compat/Makefile.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/Makefile.in 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,42 @@ +# $Id$ + +sysconfdir=@sysconfdir@ +piddir=@piddir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ + +VPATH=@srcdir@ +CC=@CC@ +LD=@LD@ +CFLAGS=@CFLAGS@ +CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ +LIBS=@LIBS@ +AR=@AR@ +RANLIB=@RANLIB@ +INSTALL=@INSTALL@ +LDFLAGS=-L. @LDFLAGS@ + +OPENBSD=base64.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o + +COMPAT=bsd-arc4random.o bsd-cray.o bsd-cygwin_util.o bsd-misc.o bsd-nextstep.o bsd-snprintf.o bsd-waitpid.o fake-getaddrinfo.o fake-getnameinfo.o + +PORTS=port-irix.o port-aix.o + +.c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + +all: libopenbsd-compat.a + +$(COMPAT): ../config.h +$(OPENBSD): ../config.h +$(PORTS): ../config.h + +libopenbsd-compat.a: $(COMPAT) $(OPENBSD) $(PORTS) + $(AR) rv $@ $(COMPAT) $(OPENBSD) $(PORTS) + $(RANLIB) $@ + +clean: + rm -f *.o *.a core + +distclean: clean + rm -f Makefile *~ Index: src/crypto/openssh/openbsd-compat/base64.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/base64.c diff -N src/crypto/openssh/openbsd-compat/base64.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/base64.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,316 @@ +/* $OpenBSD: base64.c,v 1.3 1997/11/08 20:46:55 deraadt Exp $ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include "config.h" + +#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "base64.h" + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + int i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(char const *src, u_char *target, size_t targsize) +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + +#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ Index: src/crypto/openssh/openbsd-compat/base64.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/base64.h diff -N src/crypto/openssh/openbsd-compat/base64.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/base64.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,18 @@ +/* $Id$ */ + +#ifndef _BSD_BASE64_H +#define _BSD_BASE64_H + +#include "config.h" + +#ifndef HAVE___B64_NTOP +# ifndef HAVE_B64_NTOP +int b64_ntop(u_char const *src, size_t srclength, char *target, + size_t targsize); +int b64_pton(char const *src, u_char *target, size_t targsize); +# endif /* !HAVE_B64_NTOP */ +# define __b64_ntop b64_ntop +# define __b64_pton b64_pton +#endif /* HAVE___B64_NTOP */ + +#endif /* _BSD_BASE64_H */ Index: src/crypto/openssh/openbsd-compat/bindresvport.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bindresvport.c diff -N src/crypto/openssh/openbsd-compat/bindresvport.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bindresvport.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,123 @@ +/* This file has be modified from the original OpenBSD source */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include "config.h" + +#ifndef HAVE_BINDRESVPORT_SA + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: bindresvport.c,v 1.13 2000/01/26 03:43:21 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987 by Sun Microsystems, Inc. + * + * Portions Copyright(C) 1996, Jason Downs. All rights reserved. + */ + +#include "includes.h" + +#define STARTPORT 600 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport_sa(sd, sa) + int sd; + struct sockaddr *sa; +{ + int error, af; + struct sockaddr_storage myaddr; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + u_int16_t *portp; + u_int16_t port; + socklen_t salen; + int i; + + if (sa == NULL) { + memset(&myaddr, 0, sizeof(myaddr)); + sa = (struct sockaddr *)&myaddr; + + if (getsockname(sd, sa, &salen) == -1) + return -1; /* errno is correctly set */ + + af = sa->sa_family; + memset(&myaddr, 0, salen); + } else + af = sa->sa_family; + + if (af == AF_INET) { + sin = (struct sockaddr_in *)sa; + salen = sizeof(struct sockaddr_in); + portp = &sin->sin_port; + } else if (af == AF_INET6) { + sin6 = (struct sockaddr_in6 *)sa; + salen = sizeof(struct sockaddr_in6); + portp = &sin6->sin6_port; + } else { + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + + port = ntohs(*portp); + if (port == 0) + port = (arc4random() % NPORTS) + STARTPORT; + + /* Avoid warning */ + error = -1; + + for(i = 0; i < NPORTS; i++) { + *portp = htons(port); + + error = bind(sd, sa, salen); + + /* Terminate on success */ + if (error == 0) + break; + + /* Terminate on errors, except "address already in use" */ + if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) + break; + + port++; + if (port > ENDPORT) + port = STARTPORT; + } + + return (error); +} + +#endif /* HAVE_BINDRESVPORT_SA */ Index: src/crypto/openssh/openbsd-compat/bindresvport.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bindresvport.h diff -N src/crypto/openssh/openbsd-compat/bindresvport.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bindresvport.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_BINDRESVPORT_H +#define _BSD_BINDRESVPORT_H + +#include "config.h" + +#ifndef HAVE_BINDRESVPORT_SA +int bindresvport_sa(int sd, struct sockaddr *sa); +#endif /* !HAVE_BINDRESVPORT_SA */ + +#endif /* _BSD_BINDRESVPORT_H */ Index: src/crypto/openssh/openbsd-compat/bsd-arc4random.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-arc4random.c diff -N src/crypto/openssh/openbsd-compat/bsd-arc4random.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-arc4random.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#include "log.h" + +RCSID("$Id$"); + +#ifndef HAVE_ARC4RANDOM + +#include +#include +#include + +/* Size of key to use */ +#define SEED_SIZE 20 + +/* Number of bytes to reseed after */ +#define REKEY_BYTES (1 << 24) + +static int rc4_ready = 0; +static RC4_KEY rc4; + +unsigned int arc4random(void) +{ + unsigned int r = 0; + static int first_time = 1; + + if (rc4_ready <= 0) { + if (first_time) + seed_rng(); + first_time = 0; + arc4random_stir(); + } + + RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); + + rc4_ready -= sizeof(r); + + return(r); +} + +void arc4random_stir(void) +{ + unsigned char rand_buf[SEED_SIZE]; + + memset(&rc4, 0, sizeof(rc4)); + if (!RAND_bytes(rand_buf, sizeof(rand_buf))) + fatal("Couldn't obtain random bytes (error %ld)", + ERR_get_error()); + RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); + memset(rand_buf, 0, sizeof(rand_buf)); + + rc4_ready = REKEY_BYTES; +} +#endif /* !HAVE_ARC4RANDOM */ Index: src/crypto/openssh/openbsd-compat/bsd-arc4random.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-arc4random.h diff -N src/crypto/openssh/openbsd-compat/bsd-arc4random.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-arc4random.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef _BSD_ARC4RANDOM_H +#define _BSD_ARC4RANDOM_H + +#include "config.h" + +#ifndef HAVE_ARC4RANDOM +unsigned int arc4random(void); +void arc4random_stir(void); +#endif /* !HAVE_ARC4RANDOM */ + +#endif /* _BSD_ARC4RANDOM_H */ Index: src/crypto/openssh/openbsd-compat/bsd-cray.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-cray.c diff -N src/crypto/openssh/openbsd-compat/bsd-cray.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-cray.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,300 @@ +/* + * $Id$ + * + * bsd-cray.c + * + * Copyright (c) 2002, Cray Inc. (Wendy Palm ) + * Significant portions provided by + * Wayne Schroeder, SDSC + * William Jones, UTexas + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Created: Apr 22 16.34:00 2002 wp + * + * This file contains functions required for proper execution + * on UNICOS systems. + * + */ + +#ifdef _CRAY +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bsd-cray.h" + +char cray_tmpdir[TPATHSIZ+1]; /* job TMPDIR path */ + +/* + * Functions. + */ +void cray_retain_utmp(struct utmp *, int); +void cray_delete_tmpdir(char *, int, uid_t); +void cray_init_job(struct passwd *); +void cray_set_tmpdir(struct utmp *); + + +/* + * Orignal written by: + * Wayne Schroeder + * San Diego Supercomputer Center + * schroeder@sdsc.edu +*/ +void +cray_setup(uid_t uid, char *username) +{ + struct udb *p; + extern char *setlimits(); + int i, j; + int accts[MAXVIDS]; + int naccts; + int err; + char *sr; + int pid; + struct jtab jbuf; + int jid; + + if ((jid = getjtab(&jbuf)) < 0) + fatal("getjtab: no jid"); + + err = setudb(); /* open and rewind the Cray User DataBase */ + if (err != 0) + fatal("UDB open failure"); + naccts = 0; + p = getudbnam(username); + if (p == NULL) + fatal("No UDB entry for %.100s", username); + if (uid != p->ue_uid) + fatal("UDB entry %.100s uid(%d) does not match uid %d", + username, (int) p->ue_uid, (int) uid); + for (j = 0; p->ue_acids[j] != -1 && j < MAXVIDS; j++) { + accts[naccts] = p->ue_acids[j]; + naccts++; + } + endudb(); /* close the udb */ + + if (naccts != 0) { + /* Perhaps someday we'll prompt users who have multiple accounts + to let them pick one (like CRI's login does), but for now just set + the account to the first entry. */ + if (acctid(0, accts[0]) < 0) + fatal("System call acctid failed, accts[0]=%d", accts[0]); + } + + /* Now set limits, including CPU time for the (interactive) job and process, + and set up permissions (for chown etc), etc. This is via an internal CRI + routine, setlimits, used by CRI's login. */ + + pid = getpid(); + sr = setlimits(username, C_PROC, pid, UDBRC_INTER); + if (sr != NULL) + fatal("%.200s", sr); + + sr = setlimits(username, C_JOB, jid, UDBRC_INTER); + if (sr != NULL) + fatal("%.200s", sr); + +} + +/* + * The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk + * can have pal privileges that sshd can inherit which + * could allow a user to su to root with out a password. + * This subroutine clears all privileges. + */ +void +drop_cray_privs() +{ +#if defined(_SC_CRAY_PRIV_SU) + priv_proc_t* privstate; + int result; + extern int priv_set_proc(); + extern priv_proc_t* priv_init_proc(); + struct usrv usrv; + + /* + * If ether of theses two flags are not set + * then don't allow this version of ssh to run. + */ + if (!sysconf(_SC_CRAY_PRIV_SU)) + fatal("Not PRIV_SU system."); + if (!sysconf(_SC_CRAY_POSIX_PRIV)) + fatal("Not POSIX_PRIV."); + + debug("Dropping privileges."); + + memset(&usrv, 0, sizeof(usrv)); + if (setusrv(&usrv) < 0) + fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__, + strerror(errno)); + + if ((privstate = priv_init_proc()) != NULL) { + result = priv_set_proc(privstate); + if (result != 0 ) + fatal("%s(%d): priv_set_proc(): %s", + __FILE__, __LINE__, strerror(errno)); + priv_free_proc(privstate); + } + debug ("Privileges should be cleared..."); +#else + /* XXX: do this differently */ +# error Cray systems must be run with _SC_CRAY_PRIV_SU on! +#endif +} + + +/* + * Retain utmp/wtmp information - used by cray accounting. + */ +void +cray_retain_utmp(struct utmp *ut, int pid) +{ + int fd; + struct utmp utmp; + + if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) { + while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) { + if (pid == utmp.ut_pid) { + ut->ut_jid = utmp.ut_jid; + /* XXX: MIN_SIZEOF here? can this go in loginrec? */ + strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath)); + strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host)); + strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name)); + break; + } + } + close(fd); + } + /* XXX: error message? */ +} + +/* + * tmpdir support. + */ + +/* + * find and delete jobs tmpdir. + */ +void +cray_delete_tmpdir(char *login, int jid, uid_t uid) +{ + int child; + static char jtmp[TPATHSIZ]; + struct stat statbuf; + int c; + int wstat; + + for (c = 'a'; c <= 'z'; c++) { + snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); + if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid) + break; + } + + if (c > 'z') + return; + + if ((child = fork()) == 0) { + execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL); + fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed"); + } + + while (waitpid(child, &wstat, 0) == -1 && errno == EINTR) + ; +} + +/* + * Remove tmpdir on job termination. + */ +void +cray_job_termination_handler(int sig) +{ + int jid; + char *login = NULL; + struct jtab jtab; + + debug("Received SIG JOB."); + + if ((jid = waitjob(&jtab)) == -1 || + (login = uid2nam(jtab.j_uid)) == NULL) + return; + + cray_delete_tmpdir(login, jid, jtab.j_uid); +} + +/* + * Set job id and create tmpdir directory. + */ +void +cray_init_job(struct passwd *pw) +{ + int jid; + int c; + + jid = setjob(pw->pw_uid, WJSIGNAL); + if (jid < 0) + fatal("System call setjob failure"); + + for (c = 'a'; c <= 'z'; c++) { + snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); + if (mkdir(cray_tmpdir, JTMPMODE) != 0) + continue; + if (chown(cray_tmpdir, pw->pw_uid, pw->pw_gid) != 0) { + rmdir(cray_tmpdir); + continue; + } + break; + } + + if (c > 'z') + cray_tmpdir[0] = '\0'; +} + +void +cray_set_tmpdir(struct utmp *ut) +{ + int jid; + struct jtab jbuf; + + if ((jid = getjtab(&jbuf)) < 0) + return; + + /* + * Set jid and tmpdir in utmp record. + */ + ut->ut_jid = jid; + strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ); +} +#endif Index: src/crypto/openssh/openbsd-compat/bsd-cray.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-cray.h diff -N src/crypto/openssh/openbsd-compat/bsd-cray.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-cray.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,47 @@ +/* + * $Id$ + * + * bsd-cray.h + * + * Copyright (c) 2002, Cray Inc. (Wendy Palm ) + * Significant portions provided by + * Wayne Schroeder, SDSC + * William Jones, UTexas + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Created: Apr 22 16.34:00 2002 wp + * + * This file contains functions required for proper execution + * on UNICOS systems. + * + */ +#ifndef _BSD_CRAY_H +#define _BSD_CRAY_H + +#ifdef _CRAY +void cray_init_job(struct passwd *); /* init cray job */ +void cray_job_termination_handler(int); /* process end of job signal */ +void cray_setup(uid_t, char *); /* set cray limits */ +extern char cray_tmpdir[]; /* cray tmpdir */ +#endif + +#endif /* _BSD_CRAY_H */ Index: src/crypto/openssh/openbsd-compat/bsd-cygwin_util.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-cygwin_util.c diff -N src/crypto/openssh/openbsd-compat/bsd-cygwin_util.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-cygwin_util.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,182 @@ +/* + * cygwin_util.c + * + * Copyright (c) 2000, 2001, Corinna Vinschen + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Created: Sat Sep 02 12:17:00 2000 cv + * + * This file contains functions for forcing opened file descriptors to + * binary mode on Windows systems. + */ + +#include "includes.h" + +RCSID("$Id$"); + +#ifdef HAVE_CYGWIN + +#include +#include +#include +#include +#include +#define is_winnt (GetVersion() < 0x80000000) + +#define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec")) +#define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea")) + +#if defined(open) && open == binary_open +# undef open +#endif +#if defined(pipe) && open == binary_pipe +# undef pipe +#endif + +int binary_open(const char *filename, int flags, ...) +{ + va_list ap; + mode_t mode; + + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + return open(filename, flags | O_BINARY, mode); +} + +int binary_pipe(int fd[2]) +{ + int ret = pipe(fd); + + if (!ret) { + setmode (fd[0], O_BINARY); + setmode (fd[1], O_BINARY); + } + return ret; +} + +int check_nt_auth(int pwd_authenticated, struct passwd *pw) +{ + /* + * The only authentication which is able to change the user + * context on NT systems is the password authentication. So + * we deny all requsts for changing the user context if another + * authentication method is used. + * + * This doesn't apply to Cygwin versions >= 1.3.2 anymore which + * uses the undocumented NtCreateToken() call to create a user + * token if the process has the appropriate privileges and if + * CYGWIN ntsec setting is on. + */ + static int has_create_token = -1; + + if (pw == NULL) + return 0; + if (is_winnt) { + if (has_create_token < 0) { + struct utsname uts; + int major_high = 0, major_low = 0, minor = 0; + char *cygwin = getenv("CYGWIN"); + + has_create_token = 0; + if (ntsec_on(cygwin) && !uname(&uts)) { + sscanf(uts.release, "%d.%d.%d", + &major_high, &major_low, &minor); + if (major_high > 1 || + (major_high == 1 && (major_low > 3 || + (major_low == 3 && minor >= 2)))) + has_create_token = 1; + } + } + if (has_create_token < 1 && + !pwd_authenticated && geteuid() != pw->pw_uid) + return 0; + } + return 1; +} + +int check_ntsec(const char *filename) +{ + char *cygwin; + int allow_ntea = 0; + int allow_ntsec = 0; + struct statfs fsstat; + + /* Windows 95/98/ME don't support file system security at all. */ + if (!is_winnt) + return 0; + + /* Evaluate current CYGWIN settings. */ + cygwin = getenv("CYGWIN"); + allow_ntea = ntea_on(cygwin); + allow_ntsec = ntsec_on(cygwin); + + /* + * `ntea' is an emulation of POSIX attributes. It doesn't support + * real file level security as ntsec on NTFS file systems does + * but it supports FAT filesystems. `ntea' is minimum requirement + * for security checks. + */ + if (allow_ntea) + return 1; + + /* + * Retrieve file system flags. In Cygwin, file system flags are + * copied to f_type which has no meaning in Win32 itself. + */ + if (statfs(filename, &fsstat)) + return 1; + + /* + * Only file systems supporting ACLs are able to set permissions. + * `ntsec' is the setting in Cygwin which switches using of NTFS + * ACLs to support POSIX permissions on files. + */ + if (fsstat.f_type & FS_PERSISTENT_ACLS) + return allow_ntsec; + + return 0; +} + +void register_9x_service(void) +{ + HINSTANCE kerneldll; + DWORD (*RegisterServiceProcess)(DWORD, DWORD); + + /* The service register mechanism in 9x/Me is pretty different from + * NT/2K/XP. In NT/2K/XP we're using a special service starter + * application to register and control sshd as service. This method + * doesn't play nicely with 9x/Me. For that reason we register here + * as service when running under 9x/Me. This function is only called + * by the child sshd when it's going to daemonize. + */ + if (is_winnt) + return; + if (! (kerneldll = LoadLibrary("KERNEL32.DLL"))) + return; + if (! (RegisterServiceProcess = (DWORD (*)(DWORD, DWORD)) + GetProcAddress(kerneldll, "RegisterServiceProcess"))) + return; + RegisterServiceProcess(0, 1); +} + +#endif /* HAVE_CYGWIN */ Index: src/crypto/openssh/openbsd-compat/bsd-cygwin_util.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-cygwin_util.h diff -N src/crypto/openssh/openbsd-compat/bsd-cygwin_util.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-cygwin_util.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,52 @@ +/* $Id$ */ + +/* + * cygwin_util.c + * + * Copyright (c) 2000, 2001, Corinna Vinschen + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Created: Sat Sep 02 12:17:00 2000 cv + * + * This file contains functions for forcing opened file descriptors to + * binary mode on Windows systems. + */ + +#ifndef _BSD_CYGWIN_UTIL_H +#define _BSD_CYGWIN_UTIL_H + +#ifdef HAVE_CYGWIN + +#include + +int binary_open(const char *filename, int flags, ...); +int binary_pipe(int fd[2]); +int check_nt_auth(int pwd_authenticated, struct passwd *pw); +int check_ntsec(const char *filename); +void register_9x_service(void); + +#define open binary_open +#define pipe binary_pipe + +#endif /* HAVE_CYGWIN */ + +#endif /* _BSD_CYGWIN_UTIL_H */ Index: src/crypto/openssh/openbsd-compat/bsd-misc.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-misc.c diff -N src/crypto/openssh/openbsd-compat/bsd-misc.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-misc.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +RCSID("$Id$"); + +char *get_progname(char *argv0) +{ +#ifdef HAVE___PROGNAME + extern char *__progname; + + return __progname; +#else + char *p; + + if (argv0 == NULL) + return "unknown"; /* XXX */ + p = strrchr(argv0, '/'); + if (p == NULL) + p = argv0; + else + p++; + return p; +#endif +} + +#ifndef HAVE_SETLOGIN +int setlogin(const char *name) +{ + return(0); +} +#endif /* !HAVE_SETLOGIN */ + +#ifndef HAVE_INNETGR +int innetgr(const char *netgroup, const char *host, + const char *user, const char *domain) +{ + return(0); +} +#endif /* HAVE_INNETGR */ + +#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) +int seteuid(uid_t euid) +{ + return(setreuid(-1,euid)); +} +#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ + +#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) +int setegid(uid_t egid) +{ + return(setresgid(-1,egid,-1)); +} +#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ + +#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) +const char *strerror(int e) +{ + extern int sys_nerr; + extern char *sys_errlist[]; + + if ((e >= 0) && (e < sys_nerr)) + return(sys_errlist[e]); + else + return("unlisted error"); +} +#endif + +#ifndef HAVE_UTIMES +int utimes(char *filename, struct timeval *tvp) +{ + struct utimbuf ub; + + ub.actime = tvp->tv_sec; + ub.modtime = tvp->tv_usec; + + return(utime(filename, &ub)); +} +#endif + +#ifndef HAVE_TRUNCATE +int truncate (const char *path, off_t length) +{ + int fd, ret, saverrno; + + fd = open(path, O_WRONLY); + if (fd < 0) + return -1; + + ret = ftruncate(fd, length); + saverrno = errno; + (void) close (fd); + if (ret == -1) + errno = saverrno; + return(ret); +} +#endif /* HAVE_TRUNCATE */ + +#if !defined(HAVE_SETGROUPS) && defined(SETGROUPS_NOOP) +/* + * Cygwin setgroups should be a noop. + */ +int +setgroups(size_t size, const gid_t *list) +{ + return 0; +} +#endif + Index: src/crypto/openssh/openbsd-compat/bsd-misc.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-misc.h diff -N src/crypto/openssh/openbsd-compat/bsd-misc.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-misc.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1999-2000 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef _BSD_MISC_H +#define _BSD_MISC_H + +#include "config.h" + +char *get_progname(char *argv0); + +#ifndef HAVE_SETSID +#define setsid() setpgrp(0, getpid()) +#endif /* !HAVE_SETSID */ + +#ifndef HAVE_SETENV +int setenv(const char *name, const char *value, int overwrite); +#endif /* !HAVE_SETENV */ + +#ifndef HAVE_SETLOGIN +int setlogin(const char *name); +#endif /* !HAVE_SETLOGIN */ + +#ifndef HAVE_INNETGR +int innetgr(const char *netgroup, const char *host, + const char *user, const char *domain); +#endif /* HAVE_INNETGR */ + +#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) +int seteuid(uid_t euid); +#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ + +#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) +int setegid(uid_t egid); +#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ + +#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) +const char *strerror(int e); +#endif + + +#ifndef HAVE_UTIMES +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +} +#endif /* HAVE_STRUCT_TIMEVAL */ + +int utimes(char *filename, struct timeval *tvp); +#endif /* HAVE_UTIMES */ + +#ifndef HAVE_TRUNCATE +int truncate (const char *path, off_t length); +#endif /* HAVE_TRUNCATE */ + +#if !defined(HAVE_SETGROUPS) && defined(SETGROUPS_NOOP) +int setgroups(size_t size, const gid_t *list); +#endif + + +#endif /* _BSD_MISC_H */ Index: src/crypto/openssh/openbsd-compat/bsd-nextstep.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-nextstep.c diff -N src/crypto/openssh/openbsd-compat/bsd-nextstep.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-nextstep.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,103 @@ +/* + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +RCSID("$Id$"); + +#ifdef HAVE_NEXT +#include +#include +#include "bsd-nextstep.h" + +pid_t +posix_wait(int *status) +{ + union wait statusp; + pid_t wait_pid; + + #undef wait /* Use NeXT's wait() function */ + wait_pid = wait(&statusp); + if (status) + *status = (int) statusp.w_status; + + return wait_pid; +} + +int +tcgetattr(int fd, struct termios *t) +{ + return (ioctl(fd, TIOCGETA, t)); +} + +int +tcsetattr(int fd, int opt, const struct termios *t) +{ + struct termios localterm; + + if (opt & TCSASOFT) { + localterm = *t; + localterm.c_cflag |= CIGNORE; + t = &localterm; + } + switch (opt & ~TCSASOFT) { + case TCSANOW: + return (ioctl(fd, TIOCSETA, t)); + case TCSADRAIN: + return (ioctl(fd, TIOCSETAW, t)); + case TCSAFLUSH: + return (ioctl(fd, TIOCSETAF, t)); + default: + errno = EINVAL; + return (-1); + } +} + +int tcsetpgrp(int fd, pid_t pgrp) +{ + return (ioctl(fd, TIOCSPGRP, &pgrp)); +} + +speed_t cfgetospeed(const struct termios *t) +{ + return (t->c_ospeed); +} + +speed_t cfgetispeed(const struct termios *t) +{ + return (t->c_ispeed); +} + +int +cfsetospeed(struct termios *t,int speed) +{ + t->c_ospeed = speed; + return (0); +} + +int +cfsetispeed(struct termios *t, int speed) +{ + t->c_ispeed = speed; + return (0); +} +#endif /* HAVE_NEXT */ Index: src/crypto/openssh/openbsd-compat/bsd-nextstep.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-nextstep.h diff -N src/crypto/openssh/openbsd-compat/bsd-nextstep.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-nextstep.h 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,58 @@ +/* + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* $Id$ */ + +#ifndef _NEXT_POSIX_H +#define _NEXT_POSIX_H + +#ifdef HAVE_NEXT +#include + +/* NGROUPS_MAX is behind -lposix. Use the BSD version which is NGROUPS */ +#undef NGROUPS_MAX +#define NGROUPS_MAX NGROUPS + +/* NeXT's readdir() is BSD (struct direct) not POSIX (struct dirent) */ +#define dirent direct + +/* Swap out NeXT's BSD wait() for a more POSIX complient one */ +pid_t posix_wait(int *status); +#define wait(a) posix_wait(a) + +/* #ifdef wrapped functions that need defining for clean compiling */ +pid_t getppid(void); +void vhangup(void); +int innetgr(const char *netgroup, const char *host, const char *user, + const char *domain); + +/* TERMCAP */ +int tcgetattr(int fd, struct termios *t); +int tcsetattr(int fd, int opt, const struct termios *t); +int tcsetpgrp(int fd, pid_t pgrp); +speed_t cfgetospeed(const struct termios *t); +speed_t cfgetispeed(const struct termios *t); +int cfsetospeed(struct termios *t, int speed); +int cfsetispeed(struct termios *t, int speed); +#endif /* HAVE_NEXT */ +#endif /* _NEXT_POSIX_H */ Index: src/crypto/openssh/openbsd-compat/bsd-snprintf.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-snprintf.c diff -N src/crypto/openssh/openbsd-compat/bsd-snprintf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-snprintf.c 30 Jun 2002 11:38:02 -0000 @@ -0,0 +1,744 @@ +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Ben Lindstrom 09/27/00 for OpenSSH + * Welcome to the world of %lld and %qd support. With other + * long long support. This is needed for sftp-server to work + * right. + * + * Ben Lindstrom 02/12/01 for OpenSSH + * Removed all hint of VARARGS stuff and banished it to the void, + * and did a bit of KNF style work to make things a bit more + * acceptable. Consider stealing from mutt or enlightenment. + **************************************************************/ + +#include "includes.h" + +RCSID("$Id$"); + +#if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */ +# undef HAVE_SNPRINTF +# undef HAVE_VSNPRINTF +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) + +static void +dopr(char *buffer, size_t maxlen, const char *format, va_list args); + +static void +fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, + int min, int max); + +static void +fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, + int min, int max, int flags); + +static void +fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, + int min, int max, int flags); + +static void +dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LONG_LONG 4 + +#define char_to_int(p) (p - '0') +#define abs_val(p) (p < 0 ? -p : p) + + +static void +dopr(char *buffer, size_t maxlen, const char *format, va_list args) +{ + char *strvalue; + char ch; + long value; + long double fvalue; + int min = 0; + int max = -1; + int state = DP_S_DEFAULT; + int flags = 0; + int cflags = 0; + size_t currlen = 0; + + ch = *format++; + + while (state != DP_S_DONE) { + if ((ch == '\0') || (currlen >= maxlen)) + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch(buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10*min + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10*max + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } else + state = DP_S_MOD; + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { + cflags = DP_C_LONG_LONG; + ch = *format++; + } + break; + case 'q': + cflags = DP_C_LONG_LONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg(args, int); + else if (cflags == DP_C_LONG) + value = va_arg(args, long int); + else if (cflags == DP_C_LONG_LONG) + value = va_arg (args, long long); + else + value = va_arg (args, int); + fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg(args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg(args, unsigned long int); + else if (cflags == DP_C_LONG_LONG) + value = va_arg(args, unsigned long long); + else + value = va_arg(args, unsigned int); + fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg(args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg(args, unsigned long int); + else if (cflags == DP_C_LONG_LONG) + value = va_arg(args, unsigned long long); + else + value = va_arg(args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg(args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg(args, unsigned long int); + else if (cflags == DP_C_LONG_LONG) + value = va_arg(args, unsigned long long); + else + value = va_arg(args, unsigned int); + fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, long double); + else + fvalue = va_arg(args, double); + /* um, floating point? */ + fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, long double); + else + fvalue = va_arg(args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, long double); + else + fvalue = va_arg(args, double); + break; + case 'c': + dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); + break; + case 's': + strvalue = va_arg(args, char *); + if (max < 0) + max = maxlen; /* ie, no max */ + fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg(args, void *); + fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg(args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { + long int *num; + num = va_arg(args, long int *); + *num = currlen; + } else if (cflags == DP_C_LONG_LONG) { + long long *num; + num = va_arg(args, long long *); + *num = currlen; + } else { + int *num; + num = va_arg(args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch(buffer, &currlen, maxlen, ch); + break; + case 'w': /* not supported yet, treat as next char */ + ch = *format++; + break; + default: /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else + buffer[maxlen - 1] = '\0'; +} + +static void +fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + + if (value == 0) + value = ""; + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void +fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + unsigned long uvalue; + char convert[20]; + int signvalue = 0; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if (!(flags & DP_F_UNSIGNED)) { + if (value < 0) { + signvalue = '-'; + uvalue = -value; + } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + + if (flags & DP_F_UP) + caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base]; + uvalue = (uvalue / (unsigned)base ); + } while (uvalue && (place < 20)); + if (place == 20) + place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + + + /* Spaces */ + while (spadlen > 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch(buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch(buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static long double +pow10(int exp) +{ + long double result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static long +round(long double value) +{ + long intpart = value; + + value -= intpart; + if (value >= 0.5) + intpart++; + + return intpart; +} + +static void +fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, + int min, int max, int flags) +{ + char iconvert[20]; + char fconvert[20]; + int signvalue = 0; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + long double ufvalue; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val(fvalue); + + if (fvalue < 0) + signvalue = '-'; + else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + + intpart = ufvalue; + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + fracpart = round((pow10 (max)) * (ufvalue - intpart)); + + if (fracpart >= pow10 (max)) { + intpart++; + fracpart -= pow10 (max); + } + + /* Convert integer part */ + do { + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while(intpart && (iplace < 20)); + if (iplace == 20) + iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + do { + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + } while(fracpart && (fplace < 20)); + if (fplace == 20) + fplace--; + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch(buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch(buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + dopr_outch(buffer, currlen, maxlen, '.'); + + while (fplace > 0) + dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); + + while (zpadlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (padlen < 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void +dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) + buffer[(*currlen)++] = c; +} +#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ + +#ifndef HAVE_VSNPRINTF +int +vsnprintf(char *str, size_t count, const char *fmt, va_list args) +{ + str[0] = 0; + dopr(str, count, fmt, args); + + return(strlen(str)); +} +#endif /* !HAVE_VSNPRINTF */ + +#ifndef HAVE_SNPRINTF +int +snprintf(char *str,size_t count,const char *fmt,...) +{ + va_list ap; + + va_start(ap, fmt); + (void) vsnprintf(str, count, fmt, ap); + va_end(ap); + + return(strlen(str)); +} + +#ifdef TEST_SNPRINTF +int +main(void) +{ +#define LONG_STRING 1024 + char buf1[LONG_STRING]; + char buf2[LONG_STRING]; + char *fp_fmt[] = { + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + NULL + }; + double fp_nums[] = { + -1.5, + 134.21, + 91340.2, + 341.1234, + 0203.9, + 0.96, + 0.996, + 0.9996, + 1.996, + 4.136, + 0 + }; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%lld", + "%qd", + NULL + }; + long long int_nums[] = { -1, 134, 91340, 341, 0203, 0, 9999999 }; + int x, y; + int fail = 0; + int num = 0; + + printf("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] != NULL ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + snprintf(buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\t" + "snprintf = %s\n\tsprintf = %s\n", + fp_fmt[x], buf1, buf2); + fail++; + } + num++; + } + } + for (x = 0; int_fmt[x] != NULL ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + snprintf(buf1, sizeof (buf1), int_fmt[x], int_nums[y]); + sprintf(buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\t" + "snprintf = %s\n\tsprintf = %s\n", + int_fmt[x], buf1, buf2); + fail++; + } + num++; + } + } + printf("%d tests failed out of %d.\n", fail, num); + return(0); +} +#endif /* SNPRINTF_TEST */ + +#endif /* !HAVE_SNPRINTF */ Index: src/crypto/openssh/openbsd-compat/bsd-snprintf.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-snprintf.h diff -N src/crypto/openssh/openbsd-compat/bsd-snprintf.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-snprintf.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,19 @@ +/* $Id$ */ + +#ifndef _BSD_SNPRINTF_H +#define _BSD_SNPRINTF_H + +#include "config.h" + +#include /* For size_t */ + +#ifndef HAVE_SNPRINTF +int snprintf(char *str, size_t count, const char *fmt, ...); +#endif /* !HAVE_SNPRINTF */ + +#ifndef HAVE_VSNPRINTF +int vsnprintf(char *str, size_t count, const char *fmt, va_list args); +#endif /* !HAVE_SNPRINTF */ + + +#endif /* _BSD_SNPRINTF_H */ Index: src/crypto/openssh/openbsd-compat/bsd-waitpid.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-waitpid.c diff -N src/crypto/openssh/openbsd-compat/bsd-waitpid.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-waitpid.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,52 @@ +/* + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +RCSID("$Id$"); + +#ifndef HAVE_WAITPID +#include +#include +#include "bsd-waitpid.h" + +pid_t +waitpid(int pid, int *stat_loc, int options) +{ + union wait statusp; + pid_t wait_pid; + + if (pid <= 0) { + if (pid != -1) { + errno = EINVAL; + return -1; + } + pid = 0; /* wait4() wants pid=0 for indiscriminate wait. */ + } + wait_pid = wait4(pid, &statusp, options, NULL); + if (stat_loc) + *stat_loc = (int) statusp.w_status; + + return wait_pid; +} + +#endif /* !HAVE_WAITPID */ Index: src/crypto/openssh/openbsd-compat/bsd-waitpid.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/bsd-waitpid.h diff -N src/crypto/openssh/openbsd-compat/bsd-waitpid.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/bsd-waitpid.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,49 @@ +/* + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* $Id$ */ + +#ifndef _BSD_WAITPID_H +#define _BSD_WAITPID_H + +#ifndef HAVE_WAITPID +/* Clean out any potental issues */ +#undef WIFEXITED +#undef WIFSTOPPED +#undef WIFSIGNALED + +/* Define required functions to mimic a POSIX look and feel */ +#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */ +#define WIFEXITED(w) (!((_W_INT(w)) & 0377)) +#define WIFSTOPPED(w) ((_W_INT(w)) & 0100) +#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w)) +#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1) +#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1) +#define WCOREFLAG 0x80 +#define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG) + +/* Prototype */ +pid_t waitpid(int pid, int *stat_loc, int options); + +#endif /* !HAVE_WAITPID */ +#endif /* _BSD_WAITPID_H */ Index: src/crypto/openssh/openbsd-compat/daemon.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/daemon.c diff -N src/crypto/openssh/openbsd-compat/daemon.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/daemon.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 1990, 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. + */ + +#include "includes.h" + +#ifndef HAVE_DAEMON + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: daemon.c,v 1.2 1996/08/19 08:22:13 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +int +daemon(nochdir, noclose) + int nochdir, noclose; +{ + int fd; + + switch (fork()) { + case -1: + return (-1); + case 0: +#ifdef HAVE_CYGWIN + register_9x_service(); +#endif + break; + default: +#ifdef HAVE_CYGWIN + /* + * This sleep avoids a race condition which kills the + * child process if parent is started by a NT/W2K service. + */ + sleep(1); +#endif + _exit(0); + } + + if (setsid() == -1) + return (-1); + + if (!nochdir) + (void)chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + (void)dup2(fd, STDIN_FILENO); + (void)dup2(fd, STDOUT_FILENO); + (void)dup2(fd, STDERR_FILENO); + if (fd > 2) + (void)close (fd); + } + return (0); +} + +#endif /* !HAVE_DAEMON */ + Index: src/crypto/openssh/openbsd-compat/daemon.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/daemon.h diff -N src/crypto/openssh/openbsd-compat/daemon.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/daemon.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,11 @@ +/* $Id$ */ + +#ifndef _BSD_DAEMON_H +#define _BSD_DAEMON_H + +#include "config.h" +#ifndef HAVE_DAEMON +int daemon(int nochdir, int noclose); +#endif /* !HAVE_DAEMON */ + +#endif /* _BSD_DAEMON_H */ Index: src/crypto/openssh/openbsd-compat/dirname.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/dirname.c diff -N src/crypto/openssh/openbsd-compat/dirname.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/dirname.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,80 @@ +/* $OpenBSD: dirname.c,v 1.6 2001/06/28 04:27:19 pjanzen Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#ifndef HAVE_DIRNAME + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: dirname.c,v 1.6 2001/06/28 04:27:19 pjanzen Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +char * +dirname(path) + const char *path; +{ + static char bname[MAXPATHLEN]; + register const char *endp; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + (void)strcpy(bname, "."); + return(bname); + } + + /* Strip trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* Find the start of the dir */ + while (endp > path && *endp != '/') + endp--; + + /* Either the dir is "/" or there are no slashes */ + if (endp == path) { + (void)strcpy(bname, *endp == '/' ? "/" : "."); + return(bname); + } else { + do { + endp--; + } while (endp > path && *endp == '/'); + } + + if (endp - path + 2 > sizeof(bname)) { + errno = ENAMETOOLONG; + return(NULL); + } + strlcpy(bname, path, endp - path + 2); + return(bname); +} +#endif Index: src/crypto/openssh/openbsd-compat/dirname.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/dirname.h diff -N src/crypto/openssh/openbsd-compat/dirname.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/dirname.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,5 @@ +#ifndef HAVE_DIRNAME + +char *dirname(const char *path); + +#endif Index: src/crypto/openssh/openbsd-compat/fake-gai-errnos.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-gai-errnos.h diff -N src/crypto/openssh/openbsd-compat/fake-gai-errnos.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-gai-errnos.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,14 @@ +/* + * fake library for ssh + * + * This file is included in getaddrinfo.c and getnameinfo.c. + * See getaddrinfo.c and getnameinfo.c. + */ + +/* $Id$ */ + +/* for old netdb.h */ +#ifndef EAI_NODATA +#define EAI_NODATA 1 +#define EAI_MEMORY 2 +#endif Index: src/crypto/openssh/openbsd-compat/fake-getaddrinfo.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-getaddrinfo.c diff -N src/crypto/openssh/openbsd-compat/fake-getaddrinfo.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-getaddrinfo.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,121 @@ +/* + * fake library for ssh + * + * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror(). + * These funtions are defined in rfc2133. + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For exapmle, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include "includes.h" +#include "ssh.h" + +RCSID("$Id$"); + +#ifndef HAVE_GAI_STRERROR +char *gai_strerror(int ecode) +{ + switch (ecode) { + case EAI_NODATA: + return "no address associated with hostname."; + case EAI_MEMORY: + return "memory allocation failure."; + default: + return "unknown error."; + } +} +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +void freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + do { + next = ai->ai_next; + free(ai); + } while (NULL != (ai = next)); +} +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETADDRINFO +static struct addrinfo *malloc_ai(int port, u_long addr) +{ + struct addrinfo *ai; + + ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + if (ai == NULL) + return(NULL); + + memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + + ai->ai_addr = (struct sockaddr *)(ai + 1); + /* XXX -- ssh doesn't use sa_len */ + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + + return(ai); +} + +int getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct addrinfo *cur, *prev = NULL; + struct hostent *hp; + struct in_addr in; + int i, port; + + if (servname) + port = htons(atoi(servname)); + else + port = 0; + + if (hints && hints->ai_flags & AI_PASSIVE) { + if (NULL != (*res = malloc_ai(port, htonl(0x00000000)))) + return 0; + else + return EAI_MEMORY; + } + + if (!hostname) { + if (NULL != (*res = malloc_ai(port, htonl(0x7f000001)))) + return 0; + else + return EAI_MEMORY; + } + + if (inet_aton(hostname, &in)) { + if (NULL != (*res = malloc_ai(port, in.s_addr))) + return 0; + else + return EAI_MEMORY; + } + + hp = gethostbyname(hostname); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + for (i = 0; hp->h_addr_list[i]; i++) { + cur = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr); + if (cur == NULL) { + if (*res) + freeaddrinfo(*res); + return EAI_MEMORY; + } + + if (prev) + prev->ai_next = cur; + else + *res = cur; + + prev = cur; + } + return 0; + } + + return EAI_NODATA; +} +#endif /* !HAVE_GETADDRINFO */ Index: src/crypto/openssh/openbsd-compat/fake-getaddrinfo.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-getaddrinfo.h diff -N src/crypto/openssh/openbsd-compat/fake-getaddrinfo.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-getaddrinfo.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,47 @@ +/* $Id$ */ + +#ifndef _FAKE_GETADDRINFO_H +#define _FAKE_GETADDRINFO_H + +#include "config.h" + +#include "fake-gai-errnos.h" + +#ifndef AI_PASSIVE +# define AI_PASSIVE 1 +# define AI_CANONNAME 2 +#endif + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST 2 +# define NI_NAMEREQD 4 +# define NI_NUMERICSERV 8 +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#ifndef HAVE_GETADDRINFO +int getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); +#endif /* !HAVE_GETADDRINFO */ + +#ifndef HAVE_GAI_STRERROR +char *gai_strerror(int ecode); +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +void freeaddrinfo(struct addrinfo *ai); +#endif /* !HAVE_FREEADDRINFO */ + +#endif /* _FAKE_GETADDRINFO_H */ Index: src/crypto/openssh/openbsd-compat/fake-getnameinfo.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-getnameinfo.c diff -N src/crypto/openssh/openbsd-compat/fake-getnameinfo.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-getnameinfo.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,55 @@ +/* + * fake library for ssh + * + * This file includes getnameinfo(). + * These funtions are defined in rfc2133. + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For exapmle, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include "includes.h" +#include "ssh.h" + +RCSID("$Id$"); + +#ifndef HAVE_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + char tmpserv[16]; + + if (serv) { + snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); + if (strlen(tmpserv) >= servlen) + return EAI_MEMORY; + else + strcpy(serv, tmpserv); + } + + if (host) { + if (flags & NI_NUMERICHOST) { + if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen) + return EAI_MEMORY; + + strcpy(host, inet_ntoa(sin->sin_addr)); + return 0; + } else { + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + if (hp == NULL) + return EAI_NODATA; + + if (strlen(hp->h_name) >= hostlen) + return EAI_MEMORY; + + strcpy(host, hp->h_name); + return 0; + } + } + return 0; +} +#endif /* !HAVE_GETNAMEINFO */ Index: src/crypto/openssh/openbsd-compat/fake-getnameinfo.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-getnameinfo.h diff -N src/crypto/openssh/openbsd-compat/fake-getnameinfo.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-getnameinfo.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,20 @@ +/* $Id$ */ + +#ifndef _FAKE_GETNAMEINFO_H +#define _FAKE_GETNAMEINFO_H + +#include "config.h" + +#ifndef HAVE_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags); +#endif /* !HAVE_GETNAMEINFO */ + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#endif /* _FAKE_GETNAMEINFO_H */ Index: src/crypto/openssh/openbsd-compat/fake-queue.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-queue.h diff -N src/crypto/openssh/openbsd-compat/fake-queue.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-queue.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,584 @@ +/* $OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _FAKE_QUEUE_H_ +#define _FAKE_QUEUE_H_ + +/* + * Ignore all since older platforms have broken/incomplete + * that are too hard to work around. + */ +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_ENTRY +#undef SLIST_FIRST +#undef SLIST_END +#undef SLIST_EMPTY +#undef SLIST_NEXT +#undef SLIST_FOREACH +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_REMOVE_HEAD +#undef SLIST_REMOVE +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_END +#undef LIST_EMPTY +#undef LIST_NEXT +#undef LIST_FOREACH +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_END +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_END +#undef TAILQ_NEXT +#undef TAILQ_LAST +#undef TAILQ_PREV +#undef TAILQ_EMPTY +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_INIT +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE +#undef CIRCLEQ_HEAD +#undef CIRCLEQ_HEAD_INITIALIZER +#undef CIRCLEQ_ENTRY +#undef CIRCLEQ_FIRST +#undef CIRCLEQ_LAST +#undef CIRCLEQ_END +#undef CIRCLEQ_NEXT +#undef CIRCLEQ_PREV +#undef CIRCLEQ_EMPTY +#undef CIRCLEQ_FOREACH +#undef CIRCLEQ_FOREACH_REVERSE +#undef CIRCLEQ_INIT +#undef CIRCLEQ_INSERT_AFTER +#undef CIRCLEQ_INSERT_BEFORE +#undef CIRCLEQ_INSERT_HEAD +#undef CIRCLEQ_INSERT_TAIL +#undef CIRCLEQ_REMOVE +#undef CIRCLEQ_REPLACE + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while( curelm->field.sle_next != (elm) ) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ + if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ +} while (0) + +#endif /* !_FAKE_QUEUE_H_ */ Index: src/crypto/openssh/openbsd-compat/fake-socket.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/fake-socket.h diff -N src/crypto/openssh/openbsd-compat/fake-socket.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/fake-socket.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,47 @@ +/* $Id$ */ + +#ifndef _FAKE_SOCKET_H +#define _FAKE_SOCKET_H + +#include "includes.h" +#include "sys/types.h" + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) + +struct sockaddr_storage { + struct sockaddr ss_sa; + char __ss_pad2[_SS_PADSIZE]; +}; +# define ss_family ss_sa.sa_family +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ + ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + u_int8_t s6_addr[16]; +}; +#endif /* !HAVE_STRUCT_IN6_ADDR */ + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short sin6_family; + u_int16_t sin6_port; + u_int32_t sin6_flowinfo; + struct in6_addr sin6_addr; +}; +#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +#endif /* !_FAKE_SOCKET_H */ + Index: src/crypto/openssh/openbsd-compat/getcwd.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/getcwd.c diff -N src/crypto/openssh/openbsd-compat/getcwd.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/getcwd.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1989, 1991, 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. + * + * 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. + */ + +#include "config.h" + +#if !defined(HAVE_GETCWD) + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: getcwd.c,v 1.6 2000/07/19 15:25:13 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "includes.h" + +#define ISDOT(dp) \ + (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ + (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) + +char * +getcwd(char *pt,size_t size) +{ + register struct dirent *dp; + register DIR *dir = NULL; + register dev_t dev; + register ino_t ino; + register int first; + register char *bpt, *bup; + struct stat s; + dev_t root_dev; + ino_t root_ino; + size_t ptsize, upsize; + int save_errno; + char *ept, *eup, *up; + + /* + * If no buffer specified by the user, allocate one as necessary. + * If a buffer is specified, the size has to be non-zero. The path + * is built from the end of the buffer backwards. + */ + if (pt) { + ptsize = 0; + if (!size) { + errno = EINVAL; + return (NULL); + } + ept = pt + size; + } else { + if ((pt = malloc(ptsize = 1024 - 4)) == NULL) + return (NULL); + ept = pt + ptsize; + } + bpt = ept - 1; + *bpt = '\0'; + + /* + * Allocate bytes (1024 - malloc space) for the string of "../"'s. + * Should always be enough (it's 340 levels). If it's not, allocate + * as necessary. Special * case the first stat, it's ".", not "..". + */ + if ((up = malloc(upsize = 1024 - 4)) == NULL) + goto err; + eup = up + MAXPATHLEN; + bup = up; + up[0] = '.'; + up[1] = '\0'; + + /* Save root values, so know when to stop. */ + if (stat("/", &s)) + goto err; + root_dev = s.st_dev; + root_ino = s.st_ino; + + errno = 0; /* XXX readdir has no error return. */ + + for (first = 1;; first = 0) { + /* Stat the current level. */ + if (lstat(up, &s)) + goto err; + + /* Save current node values. */ + ino = s.st_ino; + dev = s.st_dev; + + /* Check for reaching root. */ + if (root_dev == dev && root_ino == ino) { + *--bpt = '/'; + /* + * It's unclear that it's a requirement to copy the + * path to the beginning of the buffer, but it's always + * been that way and stuff would probably break. + */ + memmove(pt, bpt, ept - bpt); + free(up); + return (pt); + } + + /* + * Build pointer to the parent directory, allocating memory + * as necessary. Max length is 3 for "../", the largest + * possible component name, plus a trailing NULL. + */ + if (bup + 3 + MAXNAMLEN + 1 >= eup) { + char *nup; + + if ((nup = realloc(up, upsize *= 2)) == NULL) + goto err; + up = nup; + bup = up; + eup = up + upsize; + } + *bup++ = '.'; + *bup++ = '.'; + *bup = '\0'; + + /* Open and stat parent directory. + * RACE?? - replaced fstat(dirfd(dir), &s) w/ lstat(up,&s) + */ + if (!(dir = opendir(up)) || lstat(up,&s)) + goto err; + + /* Add trailing slash for next directory. */ + *bup++ = '/'; + + /* + * If it's a mount point, have to stat each element because + * the inode number in the directory is for the entry in the + * parent directory, not the inode number of the mounted file. + */ + save_errno = 0; + if (s.st_dev == dev) { + for (;;) { + if (!(dp = readdir(dir))) + goto notfound; + if (dp->d_fileno == ino) + break; + } + } else + for (;;) { + if (!(dp = readdir(dir))) + goto notfound; + if (ISDOT(dp)) + continue; + memmove(bup, dp->d_name, dp->d_namlen + 1); + + /* Save the first error for later. */ + if (lstat(up, &s)) { + if (!save_errno) + save_errno = errno; + errno = 0; + continue; + } + if (s.st_dev == dev && s.st_ino == ino) + break; + } + + /* + * Check for length of the current name, preceding slash, + * leading slash. + */ + if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) { + size_t len, off; + char *npt; + + if (!ptsize) { + errno = ERANGE; + goto err; + } + off = bpt - pt; + len = ept - bpt; + if ((npt = realloc(pt, ptsize *= 2)) == NULL) + goto err; + pt = npt; + bpt = pt + off; + ept = pt + ptsize; + memmove(ept - len, bpt, len); + bpt = ept - len; + } + if (!first) + *--bpt = '/'; + bpt -= dp->d_namlen; + memmove(bpt, dp->d_name, dp->d_namlen); + (void)closedir(dir); + + /* Truncate any file name. */ + *bup = '\0'; + } + +notfound: + /* + * If readdir set errno, use it, not any saved error; otherwise, + * didn't find the current directory in its parent directory, set + * errno to ENOENT. + */ + if (!errno) + errno = save_errno ? save_errno : ENOENT; + /* FALLTHROUGH */ +err: + if (ptsize) + free(pt); + if (up) + free(up); + if (dir) + (void)closedir(dir); + return (NULL); +} + +#endif /* !defined(HAVE_GETCWD) */ Index: src/crypto/openssh/openbsd-compat/getcwd.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/getcwd.h diff -N src/crypto/openssh/openbsd-compat/getcwd.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/getcwd.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_GETCWD_H +#define _BSD_GETCWD_H +#include "config.h" + +#if !defined(HAVE_GETCWD) + +char *getcwd(char *pt, size_t size); + +#endif /* !defined(HAVE_GETCWD) */ +#endif /* _BSD_GETCWD_H */ Index: src/crypto/openssh/openbsd-compat/getgrouplist.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/getgrouplist.c diff -N src/crypto/openssh/openbsd-compat/getgrouplist.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/getgrouplist.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1991, 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. + */ + +#include "includes.h" + +#ifndef HAVE_GETGROUPLIST + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: getgrouplist.c,v 1.7 1997/08/19 19:13:27 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * get credential + */ +#include +#include +#include + +int +getgrouplist(uname, agroup, groups, grpcnt) + const char *uname; + gid_t agroup; + register gid_t *groups; + int *grpcnt; +{ + register struct group *grp; + register int i, ngroups; + int ret, maxgroups; + int bail; + + ret = 0; + ngroups = 0; + maxgroups = *grpcnt; + + /* + * install primary group + */ + if (ngroups >= maxgroups) { + *grpcnt = ngroups; + return (-1); + } + groups[ngroups++] = agroup; + + /* + * Scan the group file to find additional groups. + */ + setgrent(); + while ((grp = getgrent())) { + if (grp->gr_gid == agroup) + continue; + for (bail = 0, i = 0; bail == 0 && i < ngroups; i++) + if (groups[i] == grp->gr_gid) + bail = 1; + if (bail) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], uname)) { + if (ngroups >= maxgroups) { + ret = -1; + goto out; + } + groups[ngroups++] = grp->gr_gid; + break; + } + } + } +out: + endgrent(); + *grpcnt = ngroups; + return (ret); +} + +#endif /* HAVE_GETGROUPLIST */ Index: src/crypto/openssh/openbsd-compat/getgrouplist.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/getgrouplist.h diff -N src/crypto/openssh/openbsd-compat/getgrouplist.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/getgrouplist.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,16 @@ +/* $Id$ */ + +#ifndef _BSD_GETGROUPLIST_H +#define _BSD_GETGROUPLIST_H + +#include "config.h" + +#ifndef HAVE_GETGROUPLIST + +#include + +int getgrouplist(const char *, gid_t, gid_t *, int *); + +#endif + +#endif Index: src/crypto/openssh/openbsd-compat/getopt.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/getopt.c diff -N src/crypto/openssh/openbsd-compat/getopt.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/getopt.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * 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. + */ + +#include "config.h" +#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: getopt.c,v 1.2 1996/08/19 08:33:32 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +int BSDopterr = 1, /* if error message should be printed */ + BSDoptind = 1, /* index into parent argv vector */ + BSDoptopt, /* character checked for validity */ + BSDoptreset; /* reset getopt */ +char *BSDoptarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +BSDgetopt(nargc, nargv, ostr) + int nargc; + char * const *nargv; + const char *ostr; +{ + extern char *__progname; + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (BSDoptreset || !*place) { /* update scanning pointer */ + BSDoptreset = 0; + if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++BSDoptind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((BSDoptopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, BSDoptopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (BSDoptopt == (int)'-') + return (-1); + if (!*place) + ++BSDoptind; + if (BSDopterr && *ostr != ':') + (void)fprintf(stderr, + "%s: illegal option -- %c\n", __progname, BSDoptopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + BSDoptarg = NULL; + if (!*place) + ++BSDoptind; + } + else { /* need an argument */ + if (*place) /* no white space */ + BSDoptarg = place; + else if (nargc <= ++BSDoptind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (BSDopterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + __progname, BSDoptopt); + return (BADCH); + } + else /* white space */ + BSDoptarg = nargv[BSDoptind]; + place = EMSG; + ++BSDoptind; + } + return (BSDoptopt); /* dump back option letter */ +} + +#endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */ Index: src/crypto/openssh/openbsd-compat/getopt.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/getopt.h diff -N src/crypto/openssh/openbsd-compat/getopt.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/getopt.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,14 @@ +/* $Id$ */ + +#ifndef _BSDGETOPT_H +#define _BSDGETOPT_H + +#include "config.h" + +#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) + +int BSDgetopt(int argc, char * const *argv, const char *opts); + +#endif + +#endif /* _BSDGETOPT_H */ Index: src/crypto/openssh/openbsd-compat/glob.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/glob.c diff -N src/crypto/openssh/openbsd-compat/glob.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/glob.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,915 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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. + */ + +#include "includes.h" +#include + +static long +get_arg_max(void) +{ +#ifdef ARG_MAX + return(ARG_MAX); +#elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX) + return(sysconf(_SC_ARG_MAX)); +#else + return(256); /* XXX: arbitrary */ +#endif +} + +#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ + !defined(GLOB_HAS_GL_MATCHC) + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; +#else +static char rcsid[] = "$OpenBSD: glob.c,v 1.16 2001/04/05 18:36:12 deraadt Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * glob(3) -- a superset of the one defined in POSIX 1003.2. + * + * The [!...] convention to negate a range is supported (SysV, Posix, ksh). + * + * Optional extra services, controlled by flags not defined by POSIX: + * + * GLOB_QUOTE: + * Escaping convention: \ inhibits any special meaning the following + * character might have (except \ at end of string is retained). + * GLOB_MAGCHAR: + * Set in gl_flags if pattern contained a globbing character. + * GLOB_NOMAGIC: + * Same as GLOB_NOCHECK, but it will only append pattern if it did + * not contain any magic characters. [Used in csh style globbing] + * GLOB_ALTDIRFUNC: + * Use alternately specified directory access functions. + * GLOB_TILDE: + * expand ~user/foo to the /home/dir/of/user/foo + * GLOB_BRACE: + * expand {1,2}{a,b} to 1a 1b 2a 2b + * gl_matchc: + * Number of matches in the current invocation of glob. + */ + + +#define DOLLAR '$' +#define DOT '.' +#define EOS '\0' +#define LBRACKET '[' +#define NOT '!' +#define QUESTION '?' +#define QUOTE '\\' +#define RANGE '-' +#define RBRACKET ']' +#define SEP '/' +#define STAR '*' +#define TILDE '~' +#define UNDERSCORE '_' +#define LBRACE '{' +#define RBRACE '}' +#define SLASH '/' +#define COMMA ',' + +#ifndef DEBUG + +#define M_QUOTE 0x8000 +#define M_PROTECT 0x4000 +#define M_MASK 0xffff +#define M_ASCII 0x00ff + +typedef u_short Char; + +#else + +#define M_QUOTE 0x80 +#define M_PROTECT 0x40 +#define M_MASK 0xff +#define M_ASCII 0x7f + +typedef char Char; + +#endif + + +#define CHAR(c) ((Char)((c)&M_ASCII)) +#define META(c) ((Char)((c)|M_QUOTE)) +#define M_ALL META('*') +#define M_END META(']') +#define M_NOT META('!') +#define M_ONE META('?') +#define M_RNG META('-') +#define M_SET META('[') +#define ismeta(c) (((c)&M_QUOTE) != 0) + + +static int compare __P((const void *, const void *)); +static int g_Ctoc __P((const Char *, char *, u_int)); +static int g_lstat __P((Char *, struct stat *, glob_t *)); +static DIR *g_opendir __P((Char *, glob_t *)); +static Char *g_strchr __P((Char *, int)); +static int g_stat __P((Char *, struct stat *, glob_t *)); +static int glob0 __P((const Char *, glob_t *)); +static int glob1 __P((Char *, Char *, glob_t *, size_t *)); +static int glob2 __P((Char *, Char *, Char *, Char *, Char *, Char *, + glob_t *, size_t *)); +static int glob3 __P((Char *, Char *, Char *, Char *, Char *, Char *, + Char *, Char *, glob_t *, size_t *)); +static int globextend __P((const Char *, glob_t *, size_t *)); +static const Char * + globtilde __P((const Char *, Char *, size_t, glob_t *)); +static int globexp1 __P((const Char *, glob_t *)); +static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); +static int match __P((Char *, Char *, Char *)); +#ifdef DEBUG +static void qprintf __P((const char *, Char *)); +#endif + +int +glob(pattern, flags, errfunc, pglob) + const char *pattern; + int flags, (*errfunc) __P((const char *, int)); + glob_t *pglob; +{ + const u_char *patnext; + int c; + Char *bufnext, *bufend, patbuf[MAXPATHLEN]; + + patnext = (u_char *) pattern; + if (!(flags & GLOB_APPEND)) { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_offs = 0; + } + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_errfunc = errfunc; + pglob->gl_matchc = 0; + + bufnext = patbuf; + bufend = bufnext + MAXPATHLEN - 1; + if (flags & GLOB_NOESCAPE) + while (bufnext < bufend && (c = *patnext++) != EOS) + *bufnext++ = c; + else { + /* Protect the quoted characters. */ + while (bufnext < bufend && (c = *patnext++) != EOS) + if (c == QUOTE) { + if ((c = *patnext++) == EOS) { + c = QUOTE; + --patnext; + } + *bufnext++ = c | M_PROTECT; + } else + *bufnext++ = c; + } + *bufnext = EOS; + + if (flags & GLOB_BRACE) + return globexp1(patbuf, pglob); + else + return glob0(patbuf, pglob); +} + +/* + * Expand recursively a glob {} pattern. When there is no more expansion + * invoke the standard globbing routine to glob the rest of the magic + * characters + */ +static int +globexp1(pattern, pglob) + const Char *pattern; + glob_t *pglob; +{ + const Char* ptr = pattern; + int rv; + + /* Protect a single {}, for find(1), like csh */ + if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) + return glob0(pattern, pglob); + + while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) + if (!globexp2(ptr, pattern, pglob, &rv)) + return rv; + + return glob0(pattern, pglob); +} + + +/* + * Recursive brace globbing helper. Tries to expand a single brace. + * If it succeeds then it invokes globexp1 with the new pattern. + * If it fails then it tries to glob the rest of the pattern and returns. + */ +static int +globexp2(ptr, pattern, pglob, rv) + const Char *ptr, *pattern; + glob_t *pglob; + int *rv; +{ + int i; + Char *lm, *ls; + const Char *pe, *pm, *pl; + Char patbuf[MAXPATHLEN]; + + /* copy part up to the brace */ + for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) + ; + *lm = EOS; + ls = lm; + + /* Find the balanced brace */ + for (i = 0, pe = ++ptr; *pe; pe++) + if (*pe == LBRACKET) { + /* Ignore everything between [] */ + for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) + ; + if (*pe == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pe = pm; + } + } else if (*pe == LBRACE) + i++; + else if (*pe == RBRACE) { + if (i == 0) + break; + i--; + } + + /* Non matching braces; just glob the pattern */ + if (i != 0 || *pe == EOS) { + *rv = glob0(patbuf, pglob); + return 0; + } + + for (i = 0, pl = pm = ptr; pm <= pe; pm++) { + switch (*pm) { + case LBRACKET: + /* Ignore everything between [] */ + for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) + ; + if (*pm == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pm = pl; + } + break; + + case LBRACE: + i++; + break; + + case RBRACE: + if (i) { + i--; + break; + } + /* FALLTHROUGH */ + case COMMA: + if (i && *pm == COMMA) + break; + else { + /* Append the current string */ + for (lm = ls; (pl < pm); *lm++ = *pl++) + ; + + /* + * Append the rest of the pattern after the + * closing brace + */ + for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) + ; + + /* Expand the current pattern */ +#ifdef DEBUG + qprintf("globexp2:", patbuf); +#endif + *rv = globexp1(patbuf, pglob); + + /* move after the comma, to the next string */ + pl = pm + 1; + } + break; + + default: + break; + } + } + *rv = 0; + return 0; +} + + + +/* + * expand tilde from the passwd file. + */ +static const Char * +globtilde(pattern, patbuf, patbuf_len, pglob) + const Char *pattern; + Char *patbuf; + size_t patbuf_len; + glob_t *pglob; +{ + struct passwd *pwd; + char *h; + const Char *p; + Char *b, *eb; + + if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) + return pattern; + + /* Copy up to the end of the string or / */ + eb = &patbuf[patbuf_len - 1]; + for (p = pattern + 1, h = (char *) patbuf; + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) + ; + + *h = EOS; + +#if 0 + if (h == (char *)eb) + return what; +#endif + + if (((char *) patbuf)[0] == EOS) { + /* + * handle a plain ~ or ~/ by expanding $HOME + * first and then trying the password file + */ +#if 0 + if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { +#endif + if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) { + if ((pwd = getpwuid(getuid())) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + } else { + /* + * Expand a ~user + */ + if ((pwd = getpwnam((char*) patbuf)) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + + /* Copy the home directory */ + for (b = patbuf; b < eb && *h; *b++ = *h++) + ; + + /* Append the rest of the pattern */ + while (b < eb && (*b++ = *p++) != EOS) + ; + *b = EOS; + + return patbuf; +} + + +/* + * The main glob() routine: compiles the pattern (optionally processing + * quotes), calls glob1() to do the real pattern matching, and finally + * sorts the list (unless unsorted operation is requested). Returns 0 + * if things went well, nonzero if errors occurred. It is not an error + * to find no matches. + */ +static int +glob0(pattern, pglob) + const Char *pattern; + glob_t *pglob; +{ + const Char *qpatnext; + int c, err, oldpathc; + Char *bufnext, patbuf[MAXPATHLEN]; + size_t limit = 0; + + qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); + oldpathc = pglob->gl_pathc; + bufnext = patbuf; + + /* We don't need to check for buffer overflow any more. */ + while ((c = *qpatnext++) != EOS) { + switch (c) { + case LBRACKET: + c = *qpatnext; + if (c == NOT) + ++qpatnext; + if (*qpatnext == EOS || + g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + *bufnext++ = LBRACKET; + if (c == NOT) + --qpatnext; + break; + } + *bufnext++ = M_SET; + if (c == NOT) + *bufnext++ = M_NOT; + c = *qpatnext++; + do { + *bufnext++ = CHAR(c); + if (*qpatnext == RANGE && + (c = qpatnext[1]) != RBRACKET) { + *bufnext++ = M_RNG; + *bufnext++ = CHAR(c); + qpatnext += 2; + } + } while ((c = *qpatnext++) != RBRACKET); + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_END; + break; + case QUESTION: + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_ONE; + break; + case STAR: + pglob->gl_flags |= GLOB_MAGCHAR; + /* collapse adjacent stars to one, + * to avoid exponential behavior + */ + if (bufnext == patbuf || bufnext[-1] != M_ALL) + *bufnext++ = M_ALL; + break; + default: + *bufnext++ = CHAR(c); + break; + } + } + *bufnext = EOS; +#ifdef DEBUG + qprintf("glob0:", patbuf); +#endif + + if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) + return(err); + + /* + * If there was no match we are going to append the pattern + * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified + * and the pattern did not contain any magic characters + * GLOB_NOMAGIC is there just for compatibility with csh. + */ + if (pglob->gl_pathc == oldpathc) { + if ((pglob->gl_flags & GLOB_NOCHECK) || + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR))) + return(globextend(pattern, pglob, &limit)); + else + return(GLOB_NOMATCH); + } + if (!(pglob->gl_flags & GLOB_NOSORT)) + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), compare); + return(0); +} + +static int +compare(p, q) + const void *p, *q; +{ + return(strcmp(*(char **)p, *(char **)q)); +} + +static int +glob1(pattern, pattern_last, pglob, limitp) + Char *pattern, *pattern_last; + glob_t *pglob; + size_t *limitp; +{ + Char pathbuf[MAXPATHLEN]; + + /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ + if (*pattern == EOS) + return(0); + return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, + pathbuf, pathbuf+MAXPATHLEN-1, + pattern, pattern_last, pglob, limitp)); +} + +/* + * The functions glob2 and glob3 are mutually recursive; there is one level + * of recursion for each segment in the pattern that contains one or more + * meta characters. + */ +static int +glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern, + pattern_last, pglob, limitp) + Char *pathbuf, *pathbuf_last, *pathend, *pathend_last; + Char *pattern, *pattern_last; + glob_t *pglob; + size_t *limitp; +{ + struct stat sb; + Char *p, *q; + int anymeta; + + /* + * Loop over pattern segments until end of pattern or until + * segment with meta character found. + */ + for (anymeta = 0;;) { + if (*pattern == EOS) { /* End of pattern? */ + *pathend = EOS; + if (g_lstat(pathbuf, &sb, pglob)) + return(0); + + if (((pglob->gl_flags & GLOB_MARK) && + pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || + (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { + if (pathend+1 > pathend_last) + return (1); + *pathend++ = SEP; + *pathend = EOS; + } + ++pglob->gl_matchc; + return(globextend(pathbuf, pglob, limitp)); + } + + /* Find end of next segment, copy tentatively to pathend. */ + q = pathend; + p = pattern; + while (*p != EOS && *p != SEP) { + if (ismeta(*p)) + anymeta = 1; + if (q+1 > pathend_last) + return (1); + *q++ = *p++; + } + + if (!anymeta) { /* No expansion, do next segment. */ + pathend = q; + pattern = p; + while (*pattern == SEP) { + if (pathend+1 > pathend_last) + return (1); + *pathend++ = *pattern++; + } + } else + /* Need expansion, recurse. */ + return(glob3(pathbuf, pathbuf_last, pathend, + pathend_last, pattern, pattern_last, + p, pattern_last, pglob, limitp)); + } + /* NOTREACHED */ +} + +static int +glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, + restpattern, restpattern_last, pglob, limitp) + Char *pathbuf, *pathbuf_last, *pathend, *pathend_last; + Char *pattern, *pattern_last, *restpattern, *restpattern_last; + glob_t *pglob; + size_t *limitp; +{ + register struct dirent *dp; + DIR *dirp; + int err; + char buf[MAXPATHLEN]; + + /* + * The readdirfunc declaration can't be prototyped, because it is + * assigned, below, to two functions which are prototyped in glob.h + * and dirent.h as taking pointers to differently typed opaque + * structures. + */ + struct dirent *(*readdirfunc)(); + + if (pathend > pathend_last) + return (1); + *pathend = EOS; + errno = 0; + + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { + /* TODO: don't call for ENOENT or ENOTDIR? */ + if (pglob->gl_errfunc) { + if (g_Ctoc(pathbuf, buf, sizeof(buf))) + return(GLOB_ABORTED); + if (pglob->gl_errfunc(buf, errno) || + pglob->gl_flags & GLOB_ERR) + return(GLOB_ABORTED); + } + return(0); + } + + err = 0; + + /* Search directory for matching names. */ + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + readdirfunc = pglob->gl_readdir; + else + readdirfunc = readdir; + while ((dp = (*readdirfunc)(dirp))) { + register u_char *sc; + register Char *dc; + + /* Initial DOT must be matched literally. */ + if (dp->d_name[0] == DOT && *pattern != DOT) + continue; + dc = pathend; + sc = (u_char *) dp->d_name; + while (dc < pathend_last && (*dc++ = *sc++) != EOS) + ; + if (dc >= pathend_last) { + *dc = EOS; + err = 1; + break; + } + + if (!match(pathend, pattern, restpattern)) { + *pathend = EOS; + continue; + } + err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, + restpattern, restpattern_last, pglob, limitp); + if (err) + break; + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir)(dirp); + else + closedir(dirp); + return(err); +} + + +/* + * Extend the gl_pathv member of a glob_t structure to accomodate a new item, + * add the new item, and update gl_pathc. + * + * This assumes the BSD realloc, which only copies the block when its size + * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic + * behavior. + * + * Return 0 if new item added, error code if memory couldn't be allocated. + * + * Invariant of the glob_t structure: + * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and + * gl_pathv points to (gl_offs + gl_pathc + 1) items. + */ +static int +globextend(path, pglob, limitp) + const Char *path; + glob_t *pglob; + size_t *limitp; +{ + register char **pathv; + register int i; + u_int newsize, len; + char *copy; + const Char *p; + + newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); + pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : + malloc(newsize); + if (pathv == NULL) { + if (pglob->gl_pathv) { + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + } + return(GLOB_NOSPACE); + } + + if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { + /* first time around -- clear initial gl_offs items */ + pathv += pglob->gl_offs; + for (i = pglob->gl_offs; --i >= 0; ) + *--pathv = NULL; + } + pglob->gl_pathv = pathv; + + for (p = path; *p++;) + ; + len = (size_t)(p - path); + *limitp += len; + if ((copy = malloc(len)) != NULL) { + if (g_Ctoc(path, copy, len)) { + free(copy); + return(GLOB_NOSPACE); + } + pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; + } + pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + + if ((pglob->gl_flags & GLOB_LIMIT) && + newsize + *limitp >= (u_int) get_arg_max()) { + errno = 0; + return(GLOB_NOSPACE); + } + + return(copy == NULL ? GLOB_NOSPACE : 0); +} + + +/* + * pattern matching function for filenames. Each occurrence of the * + * pattern causes a recursion level. + */ +static int +match(name, pat, patend) + register Char *name, *pat, *patend; +{ + int ok, negate_range; + Char c, k; + + while (pat < patend) { + c = *pat++; + switch (c & M_MASK) { + case M_ALL: + if (pat == patend) + return(1); + do + if (match(name, pat, patend)) + return(1); + while (*name++ != EOS) + ; + return(0); + case M_ONE: + if (*name++ == EOS) + return(0); + break; + case M_SET: + ok = 0; + if ((k = *name++) == EOS) + return(0); + if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) + ++pat; + while (((c = *pat++) & M_MASK) != M_END) + if ((*pat & M_MASK) == M_RNG) { + if (c <= k && k <= pat[1]) + ok = 1; + pat += 2; + } else if (c == k) + ok = 1; + if (ok == negate_range) + return(0); + break; + default: + if (*name++ != c) + return(0); + break; + } + } + return(*name == EOS); +} + +/* Free allocated data belonging to a glob_t structure. */ +void +globfree(pglob) + glob_t *pglob; +{ + register int i; + register char **pp; + + if (pglob->gl_pathv != NULL) { + pp = pglob->gl_pathv + pglob->gl_offs; + for (i = pglob->gl_pathc; i--; ++pp) + if (*pp) + free(*pp); + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + } +} + +static DIR * +g_opendir(str, pglob) + register Char *str; + glob_t *pglob; +{ + char buf[MAXPATHLEN]; + + if (!*str) + strcpy(buf, "."); + else { + if (g_Ctoc(str, buf, sizeof(buf))) + return(NULL); + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_opendir)(buf)); + + return(opendir(buf)); +} + +static int +g_lstat(fn, sb, pglob) + register Char *fn; + struct stat *sb; + glob_t *pglob; +{ + char buf[MAXPATHLEN]; + + if (g_Ctoc(fn, buf, sizeof(buf))) + return(-1); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_lstat)(buf, sb)); + return(lstat(buf, sb)); +} + +static int +g_stat(fn, sb, pglob) + register Char *fn; + struct stat *sb; + glob_t *pglob; +{ + char buf[MAXPATHLEN]; + + if (g_Ctoc(fn, buf, sizeof(buf))) + return(-1); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_stat)(buf, sb)); + return(stat(buf, sb)); +} + +static Char * +g_strchr(str, ch) + Char *str; + int ch; +{ + do { + if (*str == ch) + return (str); + } while (*str++); + return (NULL); +} + +static int +g_Ctoc(str, buf, len) + register const Char *str; + char *buf; + u_int len; +{ + + while (len--) { + if ((*buf++ = *str++) == EOS) + return (0); + } + return (1); +} + +#ifdef DEBUG +static void +qprintf(str, s) + const char *str; + register Char *s; +{ + register Char *p; + + (void)printf("%s:\n", str); + for (p = s; *p; p++) + (void)printf("%c", CHAR(*p)); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", *p & M_PROTECT ? '"' : ' '); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", ismeta(*p) ? '_' : ' '); + (void)printf("\n"); +} +#endif + +#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || + !defined(GLOB_HAS_GL_MATCHC) */ + Index: src/crypto/openssh/openbsd-compat/glob.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/glob.h diff -N src/crypto/openssh/openbsd-compat/glob.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/glob.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,101 @@ +/* $OpenBSD: glob.h,v 1.5 2001/03/18 17:18:58 deraadt Exp $ */ +/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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. + * + * @(#)glob.h 8.1 (Berkeley) 6/2/93 + */ + +#if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \ + !defined(GLOB_HAS_GL_MATCHC) + +#ifndef _GLOB_H_ +#define _GLOB_H_ + +struct stat; +typedef struct { + int gl_pathc; /* Count of total paths so far. */ + int gl_matchc; /* Count of paths matching pattern. */ + int gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc) __P((const char *, int)); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir) __P((void *)); + struct dirent *(*gl_readdir) __P((void *)); + void *(*gl_opendir) __P((const char *)); + int (*gl_lstat) __P((const char *, struct stat *)); + int (*gl_stat) __P((const char *, struct stat *)); +} glob_t; + +/* Flags */ +#define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +#define GLOB_ERR 0x0004 /* Return on error. */ +#define GLOB_MARK 0x0008 /* Append / to matching directories. */ +#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +#define GLOB_NOSORT 0x0020 /* Don't sort. */ + +#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ +#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ +#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ + +/* Error values returned by glob(3) */ +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABORTED (-2) /* Unignored error. */ +#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ +#define GLOB_NOSYS (-4) /* Function not supported. */ +#define GLOB_ABEND GLOB_ABORTED + +int glob __P((const char *, int, int (*)(const char *, int), glob_t *)); +void globfree __P((glob_t *)); + +#endif /* !_GLOB_H_ */ + +#endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || + !defined(GLOB_HAS_GL_MATCHC */ + Index: src/crypto/openssh/openbsd-compat/inet_aton.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/inet_aton.c diff -N src/crypto/openssh/openbsd-compat/inet_aton.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/inet_aton.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,193 @@ +/* $OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $ */ + +/* + * ++Copyright++ 1983, 1990, 1993 + * - + * Copyright (c) 1983, 1990, 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. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +#include "includes.h" + +#if !defined(HAVE_INET_ATON) + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; +static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $"; +#else +static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include + +#if 0 +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t +inet_addr(cp) + register const char *cp; +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} +#endif + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) +{ + register u_int32_t val; + register int base, n; + register char c; + unsigned int parts[4]; + register unsigned int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if ((val > 0xffffff) || (parts[0] > 0xff)) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +#endif /* !defined(HAVE_INET_ATON) */ Index: src/crypto/openssh/openbsd-compat/inet_aton.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/inet_aton.h diff -N src/crypto/openssh/openbsd-compat/inet_aton.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/inet_aton.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_INET_ATON_H +#define _BSD_INET_ATON_H + +#include "config.h" + +#ifndef HAVE_INET_ATON +int inet_aton(const char *cp, struct in_addr *addr); +#endif /* HAVE_INET_ATON */ + +#endif /* _BSD_INET_ATON_H */ Index: src/crypto/openssh/openbsd-compat/inet_ntoa.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/inet_ntoa.c diff -N src/crypto/openssh/openbsd-compat/inet_ntoa.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/inet_ntoa.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1983, 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. + */ + +#include "config.h" + +#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.2 1996/08/19 08:29:16 tholo Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ +#include +#include +#include +#include +#include "inet_ntoa.h" + +char *inet_ntoa(struct in_addr in) +{ + static char b[18]; + register char *p; + + p = (char *)∈ +#define UC(b) (((int)b)&0xff) + (void)snprintf(b, sizeof(b), + "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); + return (b); +} + +#endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */ Index: src/crypto/openssh/openbsd-compat/inet_ntoa.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/inet_ntoa.h diff -N src/crypto/openssh/openbsd-compat/inet_ntoa.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/inet_ntoa.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_INET_NTOA_H +#define _BSD_INET_NTOA_H + +#include "config.h" + +#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) +char *inet_ntoa(struct in_addr in); +#endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */ + +#endif /* _BSD_INET_NTOA_H */ Index: src/crypto/openssh/openbsd-compat/inet_ntop.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/inet_ntop.c diff -N src/crypto/openssh/openbsd-compat/inet_ntop.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/inet_ntop.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,213 @@ +/* $OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $ */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "config.h" + +#ifndef HAVE_INET_NTOP + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $"; +#else +static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include "openbsd-compat/fake-socket.h" +#include +#include +#ifndef HAVE_CYGWIN +#include +#endif +#include +#include +#include + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#endif + +#ifndef INT16SZ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], + src[3]) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + snprintf(tp, sizeof(tmp - (tp - tmp)), "%x", words[i]); + tp += strlen(tp); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +#endif /* !HAVE_INET_NTOP */ Index: src/crypto/openssh/openbsd-compat/inet_ntop.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/inet_ntop.h diff -N src/crypto/openssh/openbsd-compat/inet_ntop.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/inet_ntop.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +/* $Id$ */ + +#ifndef _BSD_INET_NTOP_H +#define _BSD_INET_NTOP_H + +#include "config.h" + +#ifndef HAVE_INET_NTOP +const char * +inet_ntop(int af, const void *src, char *dst, size_t size); +#endif /* !HAVE_INET_NTOP */ + +#endif /* _BSD_INET_NTOP_H */ Index: src/crypto/openssh/openbsd-compat/mktemp.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/mktemp.c diff -N src/crypto/openssh/openbsd-compat/mktemp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/mktemp.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,184 @@ +/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ +/* Changes: Removed mktemp */ + +/* + * Copyright (c) 1987, 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. + */ + +#include "includes.h" + +#ifndef HAVE_MKDTEMP + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: mktemp.c,v 1.14 2002/01/02 20:18:32 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#ifdef HAVE_CYGWIN +#define open binary_open +extern int binary_open(); +#endif + +static int _gettemp(char *, int *, int, int); + +int +mkstemps(path, slen) + char *path; + int slen; +{ + int fd; + + return (_gettemp(path, &fd, 0, slen) ? fd : -1); +} + +int +mkstemp(path) + char *path; +{ + int fd; + + return (_gettemp(path, &fd, 0, 0) ? fd : -1); +} + +char * +mkdtemp(path) + char *path; +{ + return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); +} + +static int +_gettemp(path, doopen, domkdir, slen) + char *path; + register int *doopen; + int domkdir; + int slen; +{ + register char *start, *trv, *suffp; + struct stat sbuf; + int rval; + pid_t pid; + + if (doopen && domkdir) { + errno = EINVAL; + return(0); + } + + for (trv = path; *trv; ++trv) + ; + trv -= slen; + suffp = trv; + --trv; + if (trv < path) { + errno = EINVAL; + return (0); + } + pid = getpid(); + while (*trv == 'X' && pid != 0) { + *trv-- = (pid % 10) + '0'; + pid /= 10; + } + while (*trv == 'X') { + char c; + + pid = (arc4random() & 0xffff) % (26+26); + if (pid < 26) + c = pid + 'A'; + else + c = (pid - 26) + 'a'; + *trv-- = c; + } + start = trv + 1; + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + if (doopen || domkdir) { + for (;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + rval = stat(path, &sbuf); + *trv = '/'; + if (rval != 0) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + break; + } + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } else if (domkdir) { + if (mkdir(path, 0700) == 0) + return(1); + if (errno != EEXIST) + return(0); + } else if (lstat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return (0); + if (*trv == 'Z') { + if (trv == suffp) + return (0); + *trv++ = 'a'; + } else { + if (isdigit(*trv)) + *trv = 'a'; + else if (*trv == 'z') /* inc from z to A */ + *trv = 'A'; + else { + if (trv == suffp) + return (0); + ++*trv; + } + break; + } + } + } + /*NOTREACHED*/ +} + +#endif /* !HAVE_MKDTEMP */ Index: src/crypto/openssh/openbsd-compat/mktemp.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/mktemp.h diff -N src/crypto/openssh/openbsd-compat/mktemp.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/mktemp.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +/* $Id$ */ + +#ifndef _BSD_MKTEMP_H +#define _BSD_MKTEMP_H + +#include "config.h" +#ifndef HAVE_MKDTEMP +int mkstemps(char *path, int slen); +int mkstemp(char *path); +char *mkdtemp(char *path); +#endif /* !HAVE_MKDTEMP */ + +#endif /* _BSD_MKTEMP_H */ Index: src/crypto/openssh/openbsd-compat/openbsd-compat.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/openbsd-compat.h diff -N src/crypto/openssh/openbsd-compat/openbsd-compat.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/openbsd-compat.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,46 @@ +/* $Id$ */ + +#ifndef _OPENBSD_H +#define _OPENBSD_H + +#include "config.h" + +/* OpenBSD function replacements */ +#include "bindresvport.h" +#include "getcwd.h" +#include "realpath.h" +#include "rresvport.h" +#include "strlcpy.h" +#include "strlcat.h" +#include "strmode.h" +#include "mktemp.h" +#include "daemon.h" +#include "dirname.h" +#include "base64.h" +#include "sigact.h" +#include "inet_ntoa.h" +#include "inet_ntop.h" +#include "strsep.h" +#include "setproctitle.h" +#include "getgrouplist.h" +#include "glob.h" +#include "readpassphrase.h" +#include "getopt.h" + +/* Home grown routines */ +#include "bsd-arc4random.h" +#include "bsd-misc.h" +#include "bsd-snprintf.h" +#include "bsd-waitpid.h" + +/* rfc2553 socket API replacements */ +#include "fake-getaddrinfo.h" +#include "fake-getnameinfo.h" +#include "fake-socket.h" + +/* Routines for a single OS platform */ +#include "bsd-cray.h" +#include "port-irix.h" +#include "port-aix.h" + +#endif /* _OPENBSD_H */ Index: src/crypto/openssh/openbsd-compat/port-aix.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/port-aix.c diff -N src/crypto/openssh/openbsd-compat/port-aix.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/port-aix.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,31 @@ +#include "includes.h" + +#ifdef _AIX + +#include +#include <../xmalloc.h> + +/* + * AIX has a "usrinfo" area where logname and + * other stuff is stored - a few applications + * actually use this and die if it's not set + */ +void +aix_usrinfo(struct passwd *pw, char *tty, int ttyfd) +{ + u_int i; + char *cp=NULL; + + if (ttyfd == -1) + tty[0] = '\0'; + cp = xmalloc(22 + strlen(tty) + 2 * strlen(pw->pw_name)); + i = sprintf(cp, "LOGNAME=%s%cNAME=%s%cTTY=%s%c%c", pw->pw_name, 0, + pw->pw_name, 0, tty, 0, 0); + if (usrinfo(SETUINFO, cp, i) == -1) + fatal("Couldn't set usrinfo: %s", strerror(errno)); + debug3("AIX/UsrInfo: set len %d", i); + xfree(cp); +} + +#endif /* _AIX */ + Index: src/crypto/openssh/openbsd-compat/port-aix.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/port-aix.h diff -N src/crypto/openssh/openbsd-compat/port-aix.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/port-aix.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,5 @@ +#ifdef _AIX + +void aix_usrinfo(struct passwd *pw, char *tty, int ttyfd); + +#endif /* _AIX */ Index: src/crypto/openssh/openbsd-compat/port-irix.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/port-irix.c diff -N src/crypto/openssh/openbsd-compat/port-irix.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/port-irix.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,61 @@ +#include "includes.h" + +#if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) + +#ifdef WITH_IRIX_PROJECT +#include +#endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_JOBS +#include +#endif +#ifdef WITH_IRIX_AUDIT +#include +#endif /* WITH_IRIX_AUDIT */ + +void +irix_setusercontext(struct passwd *pw) +{ +#ifdef WITH_IRIX_PROJECT + prid_t projid; +#endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_JOBS + jid_t jid = 0; +#else +# ifdef WITH_IRIX_ARRAY + int jid = 0; +# endif /* WITH_IRIX_ARRAY */ +#endif /* WITH_IRIX_JOBS */ + +#ifdef WITH_IRIX_JOBS + jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive"); + if (jid == -1) + fatal("Failed to create job container: %.100s", + strerror(errno)); +#endif /* WITH_IRIX_JOBS */ +#ifdef WITH_IRIX_ARRAY + /* initialize array session */ + if (jid == 0 && newarraysess() != 0) + fatal("Failed to set up new array session: %.100s", + strerror(errno)); +#endif /* WITH_IRIX_ARRAY */ +#ifdef WITH_IRIX_PROJECT + /* initialize irix project info */ + if ((projid = getdfltprojuser(pw->pw_name)) == -1) { + debug("Failed to get project id, using projid 0"); + projid = 0; + } + if (setprid(projid)) + fatal("Failed to initialize project %d for %s: %.100s", + (int)projid, pw->pw_name, strerror(errno)); +#endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_AUDIT + if (sysconf(_SC_AUDIT)) { + debug("Setting sat id to %d", (int) pw->pw_uid); + if (satsetid(pw->pw_uid)) + debug("error setting satid: %.100s", strerror(errno)); + } +#endif /* WITH_IRIX_AUDIT */ +} + + +#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ Index: src/crypto/openssh/openbsd-compat/port-irix.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/port-irix.h diff -N src/crypto/openssh/openbsd-compat/port-irix.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/port-irix.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,5 @@ +#if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) + +void irix_setusercontext(struct passwd *pw); + +#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ Index: src/crypto/openssh/openbsd-compat/readpassphrase.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/readpassphrase.c diff -N src/crypto/openssh/openbsd-compat/readpassphrase.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/readpassphrase.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,183 @@ +/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $ */ + +/* + * Copyright (c) 2000 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "includes.h" + +#ifndef HAVE_READPASSPHRASE + +#include +#include + +#ifdef TCSASOFT +# define _T_FLUSH (TCSAFLUSH|TCSASOFT) +#else +# define _T_FLUSH (TCSAFLUSH) +#endif + +/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */ +#if !defined(_POSIX_VDISABLE) && defined(VDISABLE) +# define _POSIX_VDISABLE VDISABLE +#endif + +static volatile sig_atomic_t signo; + +static void handler(int); + +char * +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) +{ + ssize_t nr; + int input, output, save_errno; + char ch, *p, *end; + struct termios term, oterm; + struct sigaction sa, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou; + + /* I suppose we could alloc on demand in this case (XXX). */ + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); + } + +restart: + /* + * Read and write to /dev/tty if available. If not, read from + * stdin and write to stderr unless a tty is required. + */ + if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if (flags & RPP_REQUIRE_TTY) { + errno = ENOTTY; + return(NULL); + } + input = STDIN_FILENO; + output = STDERR_FILENO; + } + + /* + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGALRM and SIGPIPE for now. + */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_handler = handler; + (void)sigaction(SIGINT, &sa, &saveint); + (void)sigaction(SIGHUP, &sa, &savehup); + (void)sigaction(SIGQUIT, &sa, &savequit); + (void)sigaction(SIGTERM, &sa, &saveterm); + (void)sigaction(SIGTSTP, &sa, &savetstp); + (void)sigaction(SIGTTIN, &sa, &savettin); + (void)sigaction(SIGTTOU, &sa, &savettou); + + /* Turn off echo if possible. */ + if (tcgetattr(input, &oterm) == 0) { + memcpy(&term, &oterm, sizeof(term)); + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); +#ifdef VSTATUS + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + (void)tcsetattr(input, _T_FLUSH, &term); + } else { + memset(&term, 0, sizeof(term)); + memset(&oterm, 0, sizeof(oterm)); + } + + (void)write(output, prompt, strlen(prompt)); + end = buf + bufsiz - 1; + for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch &= 0x7f; + if (isalpha(ch)) { + if ((flags & RPP_FORCELOWER)) + ch = tolower(ch); + if ((flags & RPP_FORCEUPPER)) + ch = toupper(ch); + } + *p++ = ch; + } + } + *p = '\0'; + save_errno = errno; + if (!(term.c_lflag & ECHO)) + (void)write(output, "\n", 1); + + /* Restore old terminal settings and signals. */ + if (memcmp(&term, &oterm, sizeof(term)) != 0) + (void)tcsetattr(input, _T_FLUSH, &oterm); + (void)sigaction(SIGINT, &saveint, NULL); + (void)sigaction(SIGHUP, &savehup, NULL); + (void)sigaction(SIGQUIT, &savequit, NULL); + (void)sigaction(SIGTERM, &saveterm, NULL); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); + (void)sigaction(SIGTTOU, &savettou, NULL); + if (input != STDIN_FILENO) + (void)close(input); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + if (signo) { + kill(getpid(), signo); + switch (signo) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + signo = 0; + goto restart; + } + } + + errno = save_errno; + return(nr == -1 ? NULL : buf); +} + +#if 0 +char * +getpass(const char *prompt) +{ + static char buf[_PASSWORD_LEN + 1]; + + return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); +} +#endif + +static void handler(int s) +{ + signo = s; +} +#endif /* HAVE_READPASSPHRASE */ Index: src/crypto/openssh/openbsd-compat/readpassphrase.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/readpassphrase.h diff -N src/crypto/openssh/openbsd-compat/readpassphrase.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/readpassphrase.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,48 @@ +/* $OpenBSD: readpassphrase.h,v 1.1 2000/11/21 00:48:38 millert Exp $ */ + +/* + * Copyright (c) 2000 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _READPASSPHRASE_H_ +#define _READPASSPHRASE_H_ + +#include "includes.h" + +#ifndef HAVE_READPASSPHRASE + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ + +char *readpassphrase(const char *, char *, size_t, int); + +#endif /* HAVE_READPASSPHRASE */ + +#endif /* !_READPASSPHRASE_H_ */ Index: src/crypto/openssh/openbsd-compat/realpath.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/realpath.c diff -N src/crypto/openssh/openbsd-compat/realpath.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/realpath.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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. + * + * 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. + */ + +#include "includes.h" + +#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: realpath.c,v 1.6 2002/01/12 16:24:35 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +#include +#include +#include +#include +#include + +/* + * MAXSYMLINKS + */ +#ifndef MAXSYMLINKS +#define MAXSYMLINKS 5 +#endif + +/* + * char *realpath(const char *path, char resolved_path[MAXPATHLEN]); + * + * Find the real name of path, by removing all ".", ".." and symlink + * components. Returns (resolved) on success, or (NULL) on failure, + * in which case the path which caused trouble is left in (resolved). + */ +char * +realpath(const char *path, char *resolved) +{ + struct stat sb; + int fd, n, rootd, serrno = 0; + char *p, *q, wbuf[MAXPATHLEN], start[MAXPATHLEN]; + int symlinks = 0; + + /* Save the starting point. */ + getcwd(start,MAXPATHLEN); + if ((fd = open(".", O_RDONLY)) < 0) { + (void)strcpy(resolved, "."); + return (NULL); + } + close(fd); + + /* Convert "." -> "" to optimize away a needless lstat() and chdir() */ + if (path[0] == '.' && path[1] == '\0') + path = ""; + + /* + * Find the dirname and basename from the path to be resolved. + * Change directory to the dirname component. + * lstat the basename part. + * if it is a symlink, read in the value and loop. + * if it is a directory, then change to that directory. + * get the current directory name and append the basename. + */ + strlcpy(resolved, path, MAXPATHLEN); +loop: + q = strrchr(resolved, '/'); + if (q != NULL) { + p = q + 1; + if (q == resolved) + q = "/"; + else { + do { + --q; + } while (q > resolved && *q == '/'); + q[1] = '\0'; + q = resolved; + } + if (chdir(q) < 0) + goto err1; + } else + p = resolved; + + /* Deal with the last component. */ + if (*p != '\0' && lstat(p, &sb) == 0) { + if (S_ISLNK(sb.st_mode)) { + if (++symlinks > MAXSYMLINKS) { + serrno = ELOOP; + goto err1; + } + n = readlink(p, resolved, MAXPATHLEN-1); + if (n < 0) + goto err1; + resolved[n] = '\0'; + goto loop; + } + if (S_ISDIR(sb.st_mode)) { + if (chdir(p) < 0) + goto err1; + p = ""; + } + } + + /* + * Save the last component name and get the full pathname of + * the current directory. + */ + (void)strcpy(wbuf, p); + if (getcwd(resolved, MAXPATHLEN) == 0) + goto err1; + + /* + * Join the two strings together, ensuring that the right thing + * happens if the last component is empty, or the dirname is root. + */ + if (resolved[0] == '/' && resolved[1] == '\0') + rootd = 1; + else + rootd = 0; + + if (*wbuf) { + if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { + serrno = ENAMETOOLONG; + goto err1; + } + if (rootd == 0) + (void)strcat(resolved, "/"); + (void)strcat(resolved, wbuf); + } + + /* Go back to where we came from. */ + if (chdir(start) < 0) { + serrno = errno; + goto err2; + } + return (resolved); + +err1: chdir(start); +err2: errno = serrno; + return (NULL); +} +#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ Index: src/crypto/openssh/openbsd-compat/realpath.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/realpath.h diff -N src/crypto/openssh/openbsd-compat/realpath.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/realpath.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +/* $Id$ */ + +#ifndef _BSD_REALPATH_H +#define _BSD_REALPATH_H + +#include "config.h" + +#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) + +char *realpath(const char *path, char *resolved); + +#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ +#endif /* _BSD_REALPATH_H */ Index: src/crypto/openssh/openbsd-compat/rresvport.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/rresvport.c diff -N src/crypto/openssh/openbsd-compat/rresvport.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/rresvport.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. + * Copyright (c) 1983, 1993, 1994 + * 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. + * This product includes software developed by Theo de Raadt. + * 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. + */ + +#include "config.h" + +#ifndef HAVE_RRESVPORT_AF + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: rresvport.c,v 1.5 2000/01/26 03:43:20 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "includes.h" + +#if 0 +int +rresvport(alport) + int *alport; +{ + return rresvport_af(alport, AF_INET); +} +#endif + +int +rresvport_af(int *alport, sa_family_t af) +{ + struct sockaddr_storage ss; + struct sockaddr *sa; + u_int16_t *portp; + int s; + socklen_t salen; + + memset(&ss, '\0', sizeof ss); + sa = (struct sockaddr *)&ss; + + switch (af) { + case AF_INET: + salen = sizeof(struct sockaddr_in); + portp = &((struct sockaddr_in *)sa)->sin_port; + break; + case AF_INET6: + salen = sizeof(struct sockaddr_in6); + portp = &((struct sockaddr_in6 *)sa)->sin6_port; + break; + default: + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + + s = socket(af, SOCK_STREAM, 0); + if (s < 0) + return (-1); + + *portp = htons(*alport); + if (*alport < IPPORT_RESERVED - 1) { + if (bind(s, sa, salen) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void)close(s); + return (-1); + } + } + + *portp = 0; + sa->sa_family = af; + if (bindresvport_sa(s, sa) == -1) { + (void)close(s); + return (-1); + } + *alport = ntohs(*portp); + return (s); +} + +#endif /* HAVE_RRESVPORT_AF */ Index: src/crypto/openssh/openbsd-compat/rresvport.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/rresvport.h diff -N src/crypto/openssh/openbsd-compat/rresvport.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/rresvport.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_RRESVPORT_H +#define _BSD_RRESVPORT_H + +#include "config.h" + +#ifndef HAVE_RRESVPORT_AF +int rresvport_af(int *alport, sa_family_t af); +#endif /* !HAVE_RRESVPORT_AF */ + +#endif /* _BSD_RRESVPORT_H */ Index: src/crypto/openssh/openbsd-compat/setenv.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/setenv.c diff -N src/crypto/openssh/openbsd-compat/setenv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/setenv.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1987 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. + */ + +#include "config.h" +#ifndef HAVE_SETENV + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: setenv.c,v 1.4 2001/07/09 06:57:45 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +/* + * __findenv -- + * Returns pointer to value associated with name, if any, else NULL. + * Sets offset to be the offset of the name/value combination in the + * environmental array, for use by setenv(3) and unsetenv(3). + * Explicitly removes '=' in argument name. + * + * This routine *should* be a static; don't use it. + */ +char * +__findenv(name, offset) + register const char *name; + int *offset; +{ + extern char **environ; + register int len, i; + register const char *np; + register char **p, *cp; + + if (name == NULL || environ == NULL) + return (NULL); + for (np = name; *np && *np != '='; ++np) + ; + len = np - name; + for (p = environ; (cp = *p) != NULL; ++p) { + for (np = name, i = len; i && *cp; i--) + if (*cp++ != *np++) + break; + if (i == 0 && *cp++ == '=') { + *offset = p - environ; + return (cp); + } + } + return (NULL); +} + +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +int +setenv(name, value, rewrite) + register const char *name; + register const char *value; + int rewrite; +{ + extern char **environ; + static int alloced; /* if allocated space before */ + register char *C; + int l_value, offset; + char *__findenv(); + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + if ((C = __findenv(name, &offset))) { /* find if already exists */ + if (!rewrite) + return (0); + if (strlen(C) >= l_value) { /* old larger; copy over */ + while ((*C++ = *value++)) + ; + return (0); + } + } else { /* create new slot */ + register int cnt; + register char **P; + + for (P = environ, cnt = 0; *P; ++P, ++cnt); + if (alloced) { /* just increase size */ + P = (char **)realloc((void *)environ, + (size_t)(sizeof(char *) * (cnt + 2))); + if (!P) + return (-1); + environ = P; + } + else { /* get new space */ + alloced = 1; /* copy old entries into it */ + P = (char **)malloc((size_t)(sizeof(char *) * + (cnt + 2))); + if (!P) + return (-1); + memmove(P, environ, cnt * sizeof(char *)); + environ = P; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (C = (char *)name; *C && *C != '='; ++C); /* no `=' in name */ + if (!(environ[offset] = /* name + `=' + value */ + malloc((size_t)((int)(C - name) + l_value + 2)))) + return (-1); + for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) + ; + for (*C++ = '='; (*C++ = *value++); ) + ; + return (0); +} + +/* + * unsetenv(name) -- + * Delete environmental variable "name". + */ +void +unsetenv(name) + const char *name; +{ + extern char **environ; + register char **P; + int offset; + char *__findenv(); + + while (__findenv(name, &offset)) /* if set multiple times */ + for (P = &environ[offset];; ++P) + if (!(*P = *(P + 1))) + break; +} + +#endif /* HAVE_SETENV */ Index: src/crypto/openssh/openbsd-compat/setenv.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/setenv.h diff -N src/crypto/openssh/openbsd-compat/setenv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/setenv.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,14 @@ +/* $Id$ */ + +#ifndef _BSD_SETENV_H +#define _BSD_SETENV_H + +#include "config.h" + +#ifndef HAVE_SETENV + +int setenv(register const char *name, register const char *value, int rewrite); + +#endif /* !HAVE_SETENV */ + +#endif /* _BSD_SETENV_H */ Index: src/crypto/openssh/openbsd-compat/setproctitle.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/setproctitle.c diff -N src/crypto/openssh/openbsd-compat/setproctitle.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/setproctitle.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,102 @@ +/* + * Modified for OpenSSH by Kevin Steves + * October 2000 + */ + +/* + * Copyright (c) 1994, 1995 Christopher G. Demetriou + * 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: setproctitle.c,v 1.8 2001/11/06 19:21:40 art Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "includes.h" + +#ifndef HAVE_SETPROCTITLE + +#define SPT_NONE 0 +#define SPT_PSTAT 1 + +#ifndef SPT_TYPE +#define SPT_TYPE SPT_NONE +#endif + +#if SPT_TYPE == SPT_PSTAT +#include +#include +#endif /* SPT_TYPE == SPT_PSTAT */ + +#define MAX_PROCTITLE 2048 + +extern char *__progname; + +/* + * Set Process Title (SPT) defines. Modeled after sendmail's + * SPT type definition strategy. + * + * SPT_TYPE: + * + * SPT_NONE: Don't set the process title. Default. + * SPT_PSTAT: Use pstat(PSTAT_SETCMD). HP-UX specific. + */ + +void +setproctitle(const char *fmt, ...) +{ +#if SPT_TYPE != SPT_NONE + va_list ap; + + char buf[MAX_PROCTITLE]; + size_t used; + +#if SPT_TYPE == SPT_PSTAT + union pstun pst; +#endif /* SPT_TYPE == SPT_PSTAT */ + + va_start(ap, fmt); + if (fmt != NULL) { + used = snprintf(buf, MAX_PROCTITLE, "%s: ", __progname); + if (used >= MAX_PROCTITLE) + used = MAX_PROCTITLE - 1; + (void)vsnprintf(buf + used, MAX_PROCTITLE - used, fmt, ap); + } else + (void)snprintf(buf, MAX_PROCTITLE, "%s", __progname); + va_end(ap); + used = strlen(buf); + +#if SPT_TYPE == SPT_PSTAT + pst.pst_command = buf; + pstat(PSTAT_SETCMD, pst, used, 0, 0); +#endif /* SPT_TYPE == SPT_PSTAT */ + +#endif /* SPT_TYPE != SPT_NONE */ +} +#endif /* HAVE_SETPROCTITLE */ Index: src/crypto/openssh/openbsd-compat/setproctitle.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/setproctitle.h diff -N src/crypto/openssh/openbsd-compat/setproctitle.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/setproctitle.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_SETPROCTITLE_H +#define _BSD_SETPROCTITLE_H + +#include "config.h" + +#ifndef HAVE_SETPROCTITLE +void setproctitle(const char *fmt, ...); +#endif + +#endif /* _BSD_SETPROCTITLE_H */ Index: src/crypto/openssh/openbsd-compat/sigact.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/sigact.c diff -N src/crypto/openssh/openbsd-compat/sigact.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/sigact.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,102 @@ +/* $OpenBSD: sigaction.c,v 1.3 1999/06/27 08:14:21 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim 1992,1995 * + * and: Eric S. Raymond * + ****************************************************************************/ + +#include "config.h" +#include +#include "sigact.h" + +/* This file provides sigaction() emulation using sigvec() */ +/* Use only if this is non POSIX system */ + +#if !HAVE_SIGACTION && HAVE_SIGVEC + +int +sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact) +{ + return sigvec(sig, &(sigact->sv), &(osigact->sv)); +} + +int +sigemptyset (sigset_t * mask) +{ + *mask = 0; + return 0; +} + +int +sigprocmask (int mode, sigset_t * mask, sigset_t * omask) +{ + sigset_t current = sigsetmask(0); + + if (omask) *omask = current; + + if (mode==SIG_BLOCK) + current |= *mask; + else if (mode==SIG_UNBLOCK) + current &= ~*mask; + else if (mode==SIG_SETMASK) + current = *mask; + + sigsetmask(current); + return 0; +} + +int +sigsuspend (sigset_t * mask) +{ + return sigpause(*mask); +} + +int +sigdelset (sigset_t * mask, int sig) +{ + *mask &= ~sigmask(sig); + return 0; +} + +int +sigaddset (sigset_t * mask, int sig) +{ + *mask |= sigmask(sig); + return 0; +} + +int +sigismember (sigset_t * mask, int sig) +{ + return (*mask & sigmask(sig)) != 0; +} + +#endif Index: src/crypto/openssh/openbsd-compat/sigact.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/sigact.h diff -N src/crypto/openssh/openbsd-compat/sigact.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/sigact.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,88 @@ +/* $OpenBSD: SigAction.h,v 1.2 1999/06/27 08:15:19 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim 1992,1995 * + * and: Eric S. Raymond * + ****************************************************************************/ + +/* + * $From: SigAction.h,v 1.5 1999/06/19 23:00:54 tom Exp $ + * + * This file exists to handle non-POSIX systems which don't have , + * and usually no sigaction() nor + */ + +#ifndef _SIGACTION_H +#define _SIGACTION_H + +#if !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) + +#undef SIG_BLOCK +#define SIG_BLOCK 00 + +#undef SIG_UNBLOCK +#define SIG_UNBLOCK 01 + +#undef SIG_SETMASK +#define SIG_SETMASK 02 + +/* + * is in the Linux 1.2.8 + gcc 2.7.0 configuration, + * and is useful for testing this header file. + */ +#if HAVE_BSD_SIGNAL_H +# include +#endif + +struct sigaction +{ + struct sigvec sv; +}; + +typedef unsigned long sigset_t; + +#undef sa_mask +#define sa_mask sv.sv_mask +#undef sa_handler +#define sa_handler sv.sv_handler +#undef sa_flags +#define sa_flags sv.sv_flags + +int sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact); +int sigprocmask (int how, sigset_t *mask, sigset_t *omask); +int sigemptyset (sigset_t *mask); +int sigsuspend (sigset_t *mask); +int sigdelset (sigset_t *mask, int sig); +int sigaddset (sigset_t *mask, int sig); + +#endif /* !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) */ + +#endif /* !defined(_SIGACTION_H) */ Index: src/crypto/openssh/openbsd-compat/strlcat.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strlcat.c diff -N src/crypto/openssh/openbsd-compat/strlcat.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strlcat.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,79 @@ +/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#ifndef HAVE_STRLCAT + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "strlcat.h" + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCAT */ Index: src/crypto/openssh/openbsd-compat/strlcat.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strlcat.h diff -N src/crypto/openssh/openbsd-compat/strlcat.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strlcat.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_STRLCAT_H +#define _BSD_STRLCAT_H + +#include "config.h" +#ifndef HAVE_STRLCAT +#include +size_t strlcat(char *dst, const char *src, size_t siz); +#endif /* !HAVE_STRLCAT */ + +#endif /* _BSD_STRLCAT_H */ Index: src/crypto/openssh/openbsd-compat/strlcpy.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strlcpy.c diff -N src/crypto/openssh/openbsd-compat/strlcpy.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strlcpy.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,75 @@ +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#ifndef HAVE_STRLCPY + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "strlcpy.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCPY */ Index: src/crypto/openssh/openbsd-compat/strlcpy.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strlcpy.h diff -N src/crypto/openssh/openbsd-compat/strlcpy.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strlcpy.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_STRLCPY_H +#define _BSD_STRLCPY_H + +#include "config.h" +#ifndef HAVE_STRLCPY +#include +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif /* !HAVE_STRLCPY */ + +#endif /* _BSD_STRLCPY_H */ Index: src/crypto/openssh/openbsd-compat/strmode.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strmode.c diff -N src/crypto/openssh/openbsd-compat/strmode.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strmode.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 1990 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. + */ + +#include "includes.h" +#ifndef HAVE_STRMODE + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strmode.c,v 1.3 1997/06/13 13:57:20 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +void +strmode(register mode_t mode, register char *p) +{ + /* print type */ + switch (mode & S_IFMT) { + case S_IFDIR: /* directory */ + *p++ = 'd'; + break; + case S_IFCHR: /* character special */ + *p++ = 'c'; + break; + case S_IFBLK: /* block special */ + *p++ = 'b'; + break; + case S_IFREG: /* regular */ + *p++ = '-'; + break; + case S_IFLNK: /* symbolic link */ + *p++ = 'l'; + break; +#ifdef S_IFSOCK + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#endif +#ifdef S_IFIFO + case S_IFIFO: /* fifo */ + *p++ = 'p'; + break; +#endif +#ifdef S_IFWHT + case S_IFWHT: /* whiteout */ + *p++ = 'w'; + break; +#endif + default: /* unknown */ + *p++ = '?'; + break; + } + /* usr */ + if (mode & S_IRUSR) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWUSR) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXUSR | S_ISUID)) { + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; + case S_ISUID: + *p++ = 'S'; + break; + case S_IXUSR | S_ISUID: + *p++ = 's'; + break; + } + /* group */ + if (mode & S_IRGRP) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWGRP) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXGRP | S_ISGID)) { + case 0: + *p++ = '-'; + break; + case S_IXGRP: + *p++ = 'x'; + break; + case S_ISGID: + *p++ = 'S'; + break; + case S_IXGRP | S_ISGID: + *p++ = 's'; + break; + } + /* other */ + if (mode & S_IROTH) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWOTH) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXOTH | S_ISVTX)) { + case 0: + *p++ = '-'; + break; + case S_IXOTH: + *p++ = 'x'; + break; + case S_ISVTX: + *p++ = 'T'; + break; + case S_IXOTH | S_ISVTX: + *p++ = 't'; + break; + } + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} +#endif Index: src/crypto/openssh/openbsd-compat/strmode.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strmode.h diff -N src/crypto/openssh/openbsd-compat/strmode.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strmode.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,7 @@ +/* $Id$ */ + +#ifndef HAVE_STRMODE + +void strmode(register mode_t mode, register char *p); + +#endif Index: src/crypto/openssh/openbsd-compat/strsep.c =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strsep.c diff -N src/crypto/openssh/openbsd-compat/strsep.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strsep.c 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,89 @@ +/* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */ + +/*- + * Copyright (c) 1990, 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. + */ + +#include "config.h" + +#if !defined(HAVE_STRSEP) + +#include +#include + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93"; +#else +static char *rcsid = "$OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) +{ + register char *s; + register const char *spanp; + register int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#endif /* !defined(HAVE_STRSEP) */ Index: src/crypto/openssh/openbsd-compat/strsep.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/strsep.h diff -N src/crypto/openssh/openbsd-compat/strsep.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/strsep.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _BSD_STRSEP_H +#define _BSD_STRSEP_H + +#include "config.h" + +#ifndef HAVE_STRSEP +char *strsep(char **stringp, const char *delim); +#endif /* HAVE_STRSEP */ + +#endif /* _BSD_STRSEP_H */ Index: src/crypto/openssh/openbsd-compat/tree.h =================================================================== RCS file: src/crypto/openssh/openbsd-compat/tree.h diff -N src/crypto/openssh/openbsd-compat/tree.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/openbsd-compat/tree.h 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,667 @@ +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ + \ +static __inline void \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return; \ + } \ + (head)->sph_root = (elm); \ +} \ + \ +static __inline void \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return; \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + } \ +} \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +void name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-back tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + RB_AUGMENT(RB_PARENT(elm, field)); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + RB_AUGMENT(RB_PARENT(elm, field)); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ +void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +void name##_RB_REMOVE(struct name *, struct type *); \ +struct type *name##_RB_INSERT(struct name *, struct type *); \ +struct type *name##_RB_FIND(struct name *, struct type *); \ +struct type *name##_RB_NEXT(struct name *, struct type *); \ +struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ +void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *old = elm, *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +struct type * \ +name##_RB_NEXT(struct name *head, struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(head, x)) + +#endif /* _SYS_TREE_H_ */ Index: src/crypto/openssh/pam_ssh/pam_ssh.c =================================================================== RCS file: src/crypto/openssh/pam_ssh/pam_ssh.c diff -N src/crypto/openssh/pam_ssh/pam_ssh.c --- src/crypto/openssh/pam_ssh/pam_ssh.c 7 Jan 2001 21:42:17 -0000 1.3.2.3 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,497 +0,0 @@ -/*- - * Copyright (c) 1999, 2000 Andrew J. Korty - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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. - * - * $FreeBSD: src/crypto/openssh/pam_ssh/pam_ssh.c,v 1.3.2.3 2001/01/07 21:42:17 green Exp $ - * - */ - - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define PAM_SM_AUTH -#define PAM_SM_SESSION -#include -#include - -#include - -#include "includes.h" -#include "rsa.h" -#include "key.h" -#include "ssh.h" -#include "authfd.h" -#include "authfile.h" - -#define MODULE_NAME "pam_ssh" -#define NEED_PASSPHRASE "Need passphrase for %s (%s).\nEnter passphrase: " -#define PATH_SSH_AGENT "/usr/bin/ssh-agent" - - -void -rsa_cleanup(pam_handle_t *pamh, void *data, int error_status) -{ - if (data) - RSA_free(data); -} - - -void -ssh_cleanup(pam_handle_t *pamh, void *data, int error_status) -{ - if (data) - free(data); -} - - -/* - * The following set of functions allow the module to manipulate the - * environment without calling the putenv() or setenv() stdlib functions. - * At least one version of these functions, on the first call, copies - * the environment into dynamically-allocated memory and then augments - * it. On subsequent calls, the realloc() call is used to grow the - * previously allocated buffer. Problems arise when the "environ" - * variable is changed to point to static memory after putenv()/setenv() - * have been called. - * - * We don't use putenv() or setenv() in case the application subsequently - * manipulates environ, (e.g., to clear the environment by pointing - * environ at an array of one element equal to NULL). - */ - -SLIST_HEAD(env_head, env_entry); - -struct env_entry { - char *ee_env; - SLIST_ENTRY(env_entry) ee_entries; -}; - -typedef struct env { - char **e_environ_orig; - char **e_environ_new; - int e_count; - struct env_head e_head; - int e_committed; -} ENV; - -extern char **environ; - - -static ENV * -env_new(void) -{ - ENV *self; - - if (!(self = malloc(sizeof (ENV)))) { - syslog(LOG_CRIT, "%m"); - return NULL; - } - SLIST_INIT(&self->e_head); - self->e_count = 0; - self->e_committed = 0; - return self; -} - - -static int -env_put(ENV *self, char *s) -{ - struct env_entry *env; - - if (!(env = malloc(sizeof (struct env_entry))) || - !(env->ee_env = strdup(s))) { - syslog(LOG_CRIT, "%m"); - return PAM_SERVICE_ERR; - } - SLIST_INSERT_HEAD(&self->e_head, env, ee_entries); - ++self->e_count; - return PAM_SUCCESS; -} - - -static void -env_swap(ENV *self, int which) -{ - environ = which ? self->e_environ_new : self->e_environ_orig; -} - - -static int -env_commit(ENV *self) -{ - int n; - struct env_entry *p; - char **v; - - for (v = environ, n = 0; v && *v; v++, n++) - ; - if (!(v = malloc((n + self->e_count + 1) * sizeof (char *)))) { - syslog(LOG_CRIT, "%m"); - return PAM_SERVICE_ERR; - } - self->e_committed = 1; - (void)memcpy(v, environ, n * sizeof (char *)); - SLIST_FOREACH(p, &self->e_head, ee_entries) - v[n++] = p->ee_env; - v[n] = NULL; - self->e_environ_orig = environ; - self->e_environ_new = v; - env_swap(self, 1); - return PAM_SUCCESS; -} - - -static void -env_destroy(ENV *self) -{ - struct env_entry *p; - - if (self->e_committed) - env_swap(self, 0); - SLIST_FOREACH(p, &self->e_head, ee_entries) { - free(p->ee_env); - free(p); - } - if (self->e_committed) - free(self->e_environ_new); - free(self); -} - - -void -env_cleanup(pam_handle_t *pamh, void *data, int error_status) -{ - if (data) - env_destroy(data); -} - - -typedef struct passwd PASSWD; - -PAM_EXTERN int -pam_sm_authenticate( - pam_handle_t *pamh, - int flags, - int argc, - const char **argv) -{ - char *comment_priv; /* on private key */ - char *comment_pub; /* on public key */ - char *identity; /* user's identity file */ - Key key; /* user's private key */ - int options; /* module options */ - const char *pass; /* passphrase */ - char *prompt; /* passphrase prompt */ - Key public_key; /* user's public key */ - const PASSWD *pwent; /* user's passwd entry */ - PASSWD *pwent_keep; /* our own copy */ - int retval; /* from calls */ - uid_t saved_uid; /* caller's uid */ - const char *user; /* username */ - - options = 0; - while (argc--) - pam_std_option(&options, *argv++); - if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) - return retval; - if (!((pwent = getpwnam(user)) && pwent->pw_dir)) { - /* delay? */ - return PAM_AUTH_ERR; - } - /* locate the user's private key file */ - if (!asprintf(&identity, "%s/%s", pwent->pw_dir, - SSH_CLIENT_IDENTITY)) { - syslog(LOG_CRIT, "%s: %m", MODULE_NAME); - return PAM_SERVICE_ERR; - } - /* - * Fail unless we can load the public key. Change to the - * owner's UID to appease load_public_key(). - */ - key.type = KEY_RSA; - key.rsa = RSA_new(); - public_key.type = KEY_RSA; - public_key.rsa = RSA_new(); - saved_uid = getuid(); - (void)setreuid(pwent->pw_uid, saved_uid); - retval = load_public_key(identity, &public_key, &comment_pub); - (void)setuid(saved_uid); - if (!retval) { - free(identity); - return PAM_AUTH_ERR; - } - RSA_free(public_key.rsa); - /* build the passphrase prompt */ - retval = asprintf(&prompt, NEED_PASSPHRASE, identity, comment_pub); - free(comment_pub); - if (!retval) { - syslog(LOG_CRIT, "%s: %m", MODULE_NAME); - free(identity); - return PAM_SERVICE_ERR; - } - /* pass prompt message to application and receive passphrase */ - retval = pam_get_pass(pamh, &pass, prompt, options); - free(prompt); - if (retval != PAM_SUCCESS) { - free(identity); - return retval; - } - /* - * Try to decrypt the private key with the passphrase provided. - * If success, the user is authenticated. - */ - (void)setreuid(pwent->pw_uid, saved_uid); - retval = load_private_key(identity, pass, &key, &comment_priv); - free(identity); - (void)setuid(saved_uid); - if (!retval) - return PAM_AUTH_ERR; - /* - * Save the key and comment to pass to ssh-agent in the session - * phase. - */ - if ((retval = pam_set_data(pamh, "ssh_private_key", key.rsa, - rsa_cleanup)) != PAM_SUCCESS) { - RSA_free(key.rsa); - free(comment_priv); - return retval; - } - if ((retval = pam_set_data(pamh, "ssh_key_comment", comment_priv, - ssh_cleanup)) != PAM_SUCCESS) { - free(comment_priv); - return retval; - } - /* - * Copy the passwd entry (in case successive calls are made) - * and save it for the session phase. - */ - if (!(pwent_keep = malloc(sizeof *pwent))) { - syslog(LOG_CRIT, "%m"); - return PAM_SERVICE_ERR; - } - (void)memcpy(pwent_keep, pwent, sizeof *pwent_keep); - if ((retval = pam_set_data(pamh, "ssh_passwd_entry", pwent_keep, - ssh_cleanup)) != PAM_SUCCESS) { - free(pwent_keep); - return retval; - } - return PAM_SUCCESS; -} - - -PAM_EXTERN int -pam_sm_setcred( - pam_handle_t *pamh, - int flags, - int argc, - const char **argv) -{ - return PAM_SUCCESS; -} - - -typedef AuthenticationConnection AC; - -PAM_EXTERN int -pam_sm_open_session( - pam_handle_t *pamh, - int flags, - int argc, - const char **argv) -{ - AC *ac; /* to ssh-agent */ - char *comment; /* on private key */ - char *env_end; /* end of env */ - char *env_file; /* to store env */ - FILE *env_fp; /* env_file handle */ - Key key; /* user's private key */ - FILE *pipe; /* ssh-agent handle */ - const PASSWD *pwent; /* user's passwd entry */ - int retval; /* from calls */ - uid_t saved_uid; /* caller's uid */ - ENV *ssh_env; /* env handle */ - const char *tty; /* tty or display name */ - char hname[MAXHOSTNAMELEN]; /* local hostname */ - char parse[BUFSIZ]; /* commands output */ - - /* dump output of ssh-agent in ~/.ssh */ - if ((retval = pam_get_data(pamh, "ssh_passwd_entry", - (const void **)&pwent)) != PAM_SUCCESS) - return retval; - /* use the tty or X display name in the filename */ - if ((retval = pam_get_item(pamh, PAM_TTY, (const void **)&tty)) - != PAM_SUCCESS) - return retval; - if (*tty == ':' && gethostname(hname, sizeof hname) == 0) { - if (asprintf(&env_file, "%s/.ssh/agent-%s%s", - pwent->pw_dir, hname, tty) == -1) { - syslog(LOG_CRIT, "%s: %m", MODULE_NAME); - return PAM_SERVICE_ERR; - } - } else if (asprintf(&env_file, "%s/.ssh/agent-%s", pwent->pw_dir, - tty) == -1) { - syslog(LOG_CRIT, "%s: %m", MODULE_NAME); - return PAM_SERVICE_ERR; - } - /* save the filename so we can delete the file on session close */ - if ((retval = pam_set_data(pamh, "ssh_agent_env", env_file, - ssh_cleanup)) != PAM_SUCCESS) { - free(env_file); - return retval; - } - /* start the agent as the user */ - saved_uid = geteuid(); - (void)seteuid(pwent->pw_uid); - env_fp = fopen(env_file, "w"); - pipe = popen(PATH_SSH_AGENT, "r"); - (void)seteuid(saved_uid); - if (!pipe) { - syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, PATH_SSH_AGENT); - if (env_fp) - (void)fclose(env_fp); - return PAM_SESSION_ERR; - } - if (!(ssh_env = env_new())) - return PAM_SESSION_ERR; - if ((retval = pam_set_data(pamh, "ssh_env_handle", ssh_env, - env_cleanup)) != PAM_SUCCESS) - return retval; - while (fgets(parse, sizeof parse, pipe)) { - if (env_fp) - (void)fputs(parse, env_fp); - /* - * Save environment for application with pam_putenv() - * but also with env_* functions for our own call to - * ssh_get_authentication_connection(). - */ - if (strchr(parse, '=') && (env_end = strchr(parse, ';'))) { - *env_end = '\0'; - /* pass to the application ... */ - if (!((retval = pam_putenv(pamh, parse)) == - PAM_SUCCESS)) { - (void)pclose(pipe); - if (env_fp) - (void)fclose(env_fp); - env_destroy(ssh_env); - return PAM_SERVICE_ERR; - } - env_put(ssh_env, parse); - } - } - if (env_fp) - (void)fclose(env_fp); - switch (retval = pclose(pipe)) { - case -1: - syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, PATH_SSH_AGENT); - env_destroy(ssh_env); - return PAM_SESSION_ERR; - case 0: - break; - case 127: - syslog(LOG_ERR, "%s: cannot execute %s", MODULE_NAME, - PATH_SSH_AGENT); - env_destroy(ssh_env); - return PAM_SESSION_ERR; - default: - syslog(LOG_ERR, "%s: %s exited with status %d", - MODULE_NAME, PATH_SSH_AGENT, WEXITSTATUS(retval)); - env_destroy(ssh_env); - return PAM_SESSION_ERR; - } - key.type = KEY_RSA; - /* connect to the agent and hand off the private key */ - if ((retval = pam_get_data(pamh, "ssh_private_key", - (const void **)&key.rsa)) != PAM_SUCCESS || - (retval = pam_get_data(pamh, "ssh_key_comment", - (const void **)&comment)) != PAM_SUCCESS || - (retval = env_commit(ssh_env)) != PAM_SUCCESS) { - env_destroy(ssh_env); - return retval; - } - if (!(ac = ssh_get_authentication_connection())) { - syslog(LOG_ERR, "%s: could not connect to agent", - MODULE_NAME); - env_destroy(ssh_env); - return PAM_SESSION_ERR; - } - retval = ssh_add_identity(ac, &key, comment); - ssh_close_authentication_connection(ac); - env_swap(ssh_env, 0); - return retval ? PAM_SUCCESS : PAM_SESSION_ERR; -} - - -PAM_EXTERN int -pam_sm_close_session( - pam_handle_t *pamh, - int flags, - int argc, - const char **argv) -{ - const char *env_file; /* ssh-agent environment */ - int retval; /* from calls */ - ENV *ssh_env; /* env handle */ - - if ((retval = pam_get_data(pamh, "ssh_env_handle", - (const void **)&ssh_env)) != PAM_SUCCESS) - return retval; - env_swap(ssh_env, 1); - /* kill the agent */ - retval = system(PATH_SSH_AGENT " -k"); - env_destroy(ssh_env); - switch (retval) { - case -1: - syslog(LOG_ERR, "%s: %s -k: %m", MODULE_NAME, - PATH_SSH_AGENT); - return PAM_SESSION_ERR; - case 0: - break; - case 127: - syslog(LOG_ERR, "%s: cannot execute %s -k", MODULE_NAME, - PATH_SSH_AGENT); - return PAM_SESSION_ERR; - default: - syslog(LOG_ERR, "%s: %s -k exited with status %d", - MODULE_NAME, PATH_SSH_AGENT, WEXITSTATUS(retval)); - return PAM_SESSION_ERR; - } - /* retrieve environment filename, then remove the file */ - if ((retval = pam_get_data(pamh, "ssh_agent_env", - (const void **)&env_file)) != PAM_SUCCESS) - return retval; - (void)unlink(env_file); - return PAM_SUCCESS; -} - - -PAM_MODULE_ENTRY(MODULE_NAME); Index: src/crypto/openssh/regress/Makefile =================================================================== RCS file: src/crypto/openssh/regress/Makefile diff -N src/crypto/openssh/regress/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/Makefile 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,73 @@ +# $OpenBSD: Makefile,v 1.13 2002/04/01 22:15:08 markus Exp $ + +REGRESSTARGETS= t1 t2 t3 t4 t5 t6 t7 + +CLEANFILES+= t2.out t6.out1 t6.out2 t7.out t7.out.pub + +LTESTS= connect \ + proxy-connect \ + connect-privsep \ + proto-version \ + proto-mismatch \ + exit-status \ + transfer \ + stderr-data \ + stderr-after-eof \ + broken-pipe \ + try-ciphers \ + yes-head \ + agent \ + keyscan \ + sftp \ + forwarding + +USER!= id -un +CLEANFILES+= authorized_keys_${USER} known_hosts pidfile \ + ssh_config ssh_proxy sshd_config sshd_proxy \ + rsa.pub rsa rsa1.pub rsa1 host.rsa host.rsa1 \ + rsa-agent rsa-agent.pub rsa1-agent rsa1-agent.pub \ + ls.copy + +#LTESTS+= ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp + +t1: + ssh-keygen -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv + +t2: + cat ${.CURDIR}/rsa_openssh.prv > t2.out + chmod 600 t2.out + ssh-keygen -yf t2.out | diff - ${.CURDIR}/rsa_openssh.pub + +t3: + ssh-keygen -ef ${.CURDIR}/rsa_openssh.pub |\ + ssh-keygen -if /dev/stdin |\ + diff - ${.CURDIR}/rsa_openssh.pub + +t4: + ssh-keygen -lf ${.CURDIR}/rsa_openssh.pub |\ + awk '{print $$2}' | diff - ${.CURDIR}/t4.ok + +t5: + ssh-keygen -Bf ${.CURDIR}/rsa_openssh.pub |\ + awk '{print $$2}' | diff - ${.CURDIR}/t5.ok + +t6: + ssh-keygen -if ${.CURDIR}/dsa_ssh2.prv > t6.out1 + ssh-keygen -if ${.CURDIR}/dsa_ssh2.pub > t6.out2 + chmod 600 t6.out1 + ssh-keygen -yf t6.out1 | diff - t6.out2 + +t7.out: + ssh-keygen -q -t rsa -N '' -f $@ + +t7: t7.out + ssh-keygen -lf t7.out > /dev/null + ssh-keygen -Bf t7.out > /dev/null + +.for t in ${LTESTS} +REGRESSTARGETS+=t-${t} +t-${t}: + sh ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/${t}.sh +.endfor + +.include "bsd.regress.mk" Index: src/crypto/openssh/regress/agent.sh =================================================================== RCS file: src/crypto/openssh/regress/agent.sh diff -N src/crypto/openssh/regress/agent.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/agent.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,75 @@ +# $OpenBSD: agent.sh,v 1.6 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="simple agent test" + +SSH_AUTH_SOCK=/nonexistant ${SSHADD} -l > /dev/null 2>&1 +if [ $? -ne 2 ]; then + fail "ssh-add -l did not fail with exit code 2" +fi + +trace "start agent" +eval `${SSHAGENT} -s` > /dev/null +r=$? +if [ $r -ne 0 ]; then + fail "could not start ssh-agent: exit code $r" +else + ${SSHADD} -l > /dev/null 2>&1 + if [ $? -ne 1 ]; then + fail "ssh-add -l did not fail with exit code 1" + fi + trace "overwrite authorized keys" + echo -n > $OBJ/authorized_keys_$USER + for t in rsa rsa1; do + # generate user key for agent + rm -f $OBJ/$t-agent + ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\ + fail "ssh-keygen for $t-agent failed" + # add to authorized keys + cat $OBJ/$t-agent.pub >> $OBJ/authorized_keys_$USER + # add privat key to agent + ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh-add did succeed exit code 0" + fi + done + ${SSHADD} -l > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh-add -l failed: exit code $?" + fi + # the same for full pubkey output + ${SSHADD} -L > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh-add -L failed: exit code $?" + fi + + trace "simple connect via agent" + for p in 1 2; do + ${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p + if [ $? -ne 5$p ]; then + fail "ssh connect with protocol $p failed (exit code $?)" + fi + done + + trace "agent forwarding" + for p in 1 2; do + ${SSH} -A -$p -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh-add -l via agent fwd proto $p failed (exit code $?)" + fi + ${SSH} -A -$p -F $OBJ/ssh_proxy somehost \ + "${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p" + if [ $? -ne 5$p ]; then + fail "agent fwd proto $p failed (exit code $?)" + fi + done + + trace "delete all agent keys" + ${SSHADD} -D > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh-add -D failed: exit code $?" + fi + + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi Index: src/crypto/openssh/regress/authorized_keys_root =================================================================== RCS file: src/crypto/openssh/regress/authorized_keys_root diff -N src/crypto/openssh/regress/authorized_keys_root --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/authorized_keys_root 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,2 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAt6ttBacbgvLPsF1VWWfT51t55/5Mj62Xp8EaoH5SNSaLiGIgrrja077lKEept75U4uKFUYU5JJX9GPE9A7Y43LXv+/A6Jm4rEj/U0s4H8tf0UmzVC3t6xh0sRK0hYVNILyoHnIAgdY8CmOiybw7p6DxJY8MRAehD3n9+kFcachU= root@xenon +1024 35 132789427207755621599908461558918671787816692978751485815532032934821830960131244604702969298486352138126114080367609979552547448841583955126231410604842765726397407176910594168641969541792069550006878863592030567875913190224374005367884774859544943329148178663694126456638431428703289837638970464685771819219 root@xenon Index: src/crypto/openssh/regress/broken-pipe.sh =================================================================== RCS file: src/crypto/openssh/regress/broken-pipe.sh diff -N src/crypto/openssh/regress/broken-pipe.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/broken-pipe.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,15 @@ +# $OpenBSD: broken-pipe.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="broken pipe test" + +for p in 1 2; do + trace "protocol $p" + for i in 1 2 3 4; do + ${SSH} -$p -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true + r=$? + if [ $r -ne 0 ]; then + fail "broken pipe returns $r for protocol $p" + fi + done +done Index: src/crypto/openssh/regress/bsd.regress.mk =================================================================== RCS file: src/crypto/openssh/regress/bsd.regress.mk diff -N src/crypto/openssh/regress/bsd.regress.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/bsd.regress.mk 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,79 @@ +# $OpenBSD: bsd.regress.mk,v 1.9 2002/02/17 01:10:15 marc Exp $ +# No man pages for regression tests. +NOMAN= + +# No installation. +install: + +# If REGRESSTARGETS is defined and PROG is not defined, set NOPROG +.if defined(REGRESSTARGETS) && !defined(PROG) +NOPROG= +.endif + +.include + +.MAIN: all +all: regress + +# XXX - Need full path to REGRESSLOG, otherwise there will be much pain. + +REGRESSLOG?=/dev/null +REGRESSNAME=${.CURDIR:S/${BSDSRCDIR}\/regress\///} + +.if defined(PROG) && !empty(PROG) +run-regress-${PROG}: ${PROG} + ./${PROG} +.endif + +.if !defined(REGRESSTARGETS) +REGRESSTARGETS=run-regress-${PROG} +. if defined(REGRESSSKIP) +REGRESSSKIPTARGETS=run-regress-${PROG} +. endif +.endif + +REGRESSSKIPSLOW?=no + +#.if (${REGRESSSKIPSLOW:L} == "yes") && defined(REGRESSSLOWTARGETS) + +.if (${REGRESSSKIPSLOW} == "yes") && defined(REGRESSSLOWTARGETS) +REGRESSSKIPTARGETS+=${REGRESSSLOWTARGETS} +.endif + +.if defined(REGRESSROOTTARGETS) +ROOTUSER!=id -g +SUDO?= +. if (${ROOTUSER} != 0) && empty(SUDO) +REGRESSSKIPTARGETS+=${REGRESSROOTTARGETS} +. endif +.endif + +REGRESSSKIPTARGETS?= + +regress: +.for RT in ${REGRESSTARGETS} +. if ${REGRESSSKIPTARGETS:M${RT}} + @echo -n "SKIP " >> ${REGRESSLOG} +. else +# XXX - we need a better method to see if a test fails due to timeout or just +# normal failure. +. if !defined(REGRESSMAXTIME) + @if cd ${.CURDIR} && ${MAKE} ${RT}; then \ + echo -n "SUCCESS " >> ${REGRESSLOG} ; \ + else \ + echo -n "FAIL " >> ${REGRESSLOG} ; \ + echo FAILED ; \ + fi +. else + @if cd ${.CURDIR} && (ulimit -t ${REGRESSMAXTIME} ; ${MAKE} ${RT}); then \ + echo -n "SUCCESS " >> ${REGRESSLOG} ; \ + else \ + echo -n "FAIL (possible timeout) " >> ${REGRESSLOG} ; \ + echo FAILED ; \ + fi +. endif +. endif + @echo ${REGRESSNAME}/${RT:S/^run-regress-//} >> ${REGRESSLOG} +.endfor + +.PHONY: regress Index: src/crypto/openssh/regress/connect-privsep.sh =================================================================== RCS file: src/crypto/openssh/regress/connect-privsep.sh diff -N src/crypto/openssh/regress/connect-privsep.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/connect-privsep.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +# $OpenBSD: connect-privsep.sh,v 1.1 2002/03/21 21:45:07 markus Exp $ +# Placed in the Public Domain. + +tid="proxy connect with privsep" + +echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy + +for p in 1 2; do + ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true + if [ $? -ne 0 ]; then + fail "ssh privsep+proxyconnect protocol $p failed" + fi +done Index: src/crypto/openssh/regress/connect.sh =================================================================== RCS file: src/crypto/openssh/regress/connect.sh diff -N src/crypto/openssh/regress/connect.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/connect.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +# $OpenBSD: connect.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="simple connect" + +start_sshd + +for p in 1 2; do + ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true + if [ $? -ne 0 ]; then + fail "ssh connect with protocol $p failed" + fi +done Index: src/crypto/openssh/regress/copy.1 =================================================================== RCS file: src/crypto/openssh/regress/copy.1 diff -N src/crypto/openssh/regress/copy.1 Binary files /dev/null and copy.1 differ Index: src/crypto/openssh/regress/copy.2 =================================================================== RCS file: src/crypto/openssh/regress/copy.2 diff -N src/crypto/openssh/regress/copy.2 Binary files /dev/null and copy.2 differ Index: src/crypto/openssh/regress/dsa_ssh2.prv =================================================================== RCS file: src/crypto/openssh/regress/dsa_ssh2.prv diff -N src/crypto/openssh/regress/dsa_ssh2.prv --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/dsa_ssh2.prv 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,14 @@ +---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ---- +Subject: ssh-keygen test +Comment: "1024-bit dsa, Tue Jan 08 2002 22:00:23 +0100" +P2/56wAAAgIAAAAmZGwtbW9kcHtzaWdue2RzYS1uaXN0LXNoYTF9LGRoe3BsYWlufX0AAA +AEbm9uZQAAAcQAAAHAAAAAAAAABACwUfm3AxZTut3icBmwCcD48nY64HzuELlQ+vEqjIcR +Lo49es/DQTeLNQ+kdKRCfouosGNv0WqxRtF0tUsWdXxS37oHGa4QPugBdHRd7YlZGZv8kg +x7FsoepY7v7E683/97dv2zxL3AGagTEzWr7fl0yPexAaZoDvtQrrjX44BLmwAABACWQkvv +MxnD8eFkS1konFfMJ1CkuRfTN34CBZ6dY7VTSGemy4QwtFdMKmoufD0eKgy3p5WOeWCYKt +F4FhjHKZk/aaxFjjIbtkrnlvXg64QI11dSZyBN6/ViQkHPSkUDF+A6AAEhrNbQbAFSvao1 +kTvNtPCtL0AkUIduEMzGQfLCTAAAAKDeC043YVo9Zo0zAEeIA4uZh4LBCQAAA/9aj7Y5ik +ehygJ4qTDSlVypsPuV+n59tMS0e2pfrSG87yf5r94AKBmJeho5OO6wYaXCxsVB7AFbSUD6 +75AK8mHF4v1/+7SWKk5f8xlMCMSPZ9K0+j/W1d/q2qkhnnDZolOHDomLA+U00i5ya/jnTV +zyDPWLFpWK8u3xGBPAYX324gAAAKDHFvooRnaXdZbeWGTTqmgHB1GU9A== +---- END SSH2 ENCRYPTED PRIVATE KEY ---- Index: src/crypto/openssh/regress/dsa_ssh2.pub =================================================================== RCS file: src/crypto/openssh/regress/dsa_ssh2.pub diff -N src/crypto/openssh/regress/dsa_ssh2.pub --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/dsa_ssh2.pub 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Subject: ssh-keygen test +Comment: "1024-bit dsa, Tue Jan 08 2002 22:00:23 +0100" +AAAAB3NzaC1kc3MAAACBALBR+bcDFlO63eJwGbAJwPjydjrgfO4QuVD68SqMhxEujj16z8 +NBN4s1D6R0pEJ+i6iwY2/RarFG0XS1SxZ1fFLfugcZrhA+6AF0dF3tiVkZm/ySDHsWyh6l +ju/sTrzf/3t2/bPEvcAZqBMTNavt+XTI97EBpmgO+1CuuNfjgEubAAAAFQDeC043YVo9Zo +0zAEeIA4uZh4LBCQAAAIEAlkJL7zMZw/HhZEtZKJxXzCdQpLkX0zd+AgWenWO1U0hnpsuE +MLRXTCpqLnw9HioMt6eVjnlgmCrReBYYxymZP2msRY4yG7ZK55b14OuECNdXUmcgTev1Yk +JBz0pFAxfgOgABIazW0GwBUr2qNZE7zbTwrS9AJFCHbhDMxkHywkwAAACAWo+2OYpHocoC +eKkw0pVcqbD7lfp+fbTEtHtqX60hvO8n+a/eACgZiXoaOTjusGGlwsbFQewBW0lA+u+QCv +JhxeL9f/u0lipOX/MZTAjEj2fStPo/1tXf6tqpIZ5w2aJThw6JiwPlNNIucmv4501c8gz1 +ixaVivLt8RgTwGF99uI= +---- END SSH2 PUBLIC KEY ---- Index: src/crypto/openssh/regress/exit-status.sh =================================================================== RCS file: src/crypto/openssh/regress/exit-status.sh diff -N src/crypto/openssh/regress/exit-status.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/exit-status.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,24 @@ +# $OpenBSD: exit-status.sh,v 1.6 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="remote exit status" + +for p in 1 2; do + for s in 0 1 4 5 44; do + trace "proto $p status $s" + verbose "test $tid: proto $p status $s" + ${SSH} -$p -F $OBJ/ssh_proxy otherhost exit $s + r=$? + if [ $r -ne $s ]; then + fail "exit code mismatch for protocol $p: $r != $s" + fi + + # same with early close of stdout/err + ${SSH} -$p -F $OBJ/ssh_proxy -n otherhost \ + exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\' + r=$? + if [ $r -ne $s ]; then + fail "exit code (with sleep) mismatch for protocol $p: $r != $s" + fi + done +done Index: src/crypto/openssh/regress/forwarding.sh =================================================================== RCS file: src/crypto/openssh/regress/forwarding.sh diff -N src/crypto/openssh/regress/forwarding.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/forwarding.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,33 @@ +# $OpenBSD: forwarding.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="local and remote forwarding" + +start_sshd + +base=33 +last=$PORT +fwd="" +for j in 0 1 2; do + for i in 0 1 2; do + a=$base$j$i + b=`expr $a + 50` + c=$last + # fwd chain: $a -> $b -> $c + fwd="$fwd -L$a:127.0.0.1:$b -R$b:127.0.0.1:$c" + last=$a + done +done +for p in 1 2; do + q=`expr 3 - $p` + trace "start forwarding, fork to background" + ${SSH} -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10 + + trace "transfer over forwarded channels and check result" + ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ + somehost cat /bin/ls > $OBJ/ls.copy + test -f $OBJ/ls.copy || fail "failed copy /bin/ls" + cmp /bin/ls $OBJ/ls.copy || fail "corrupted copy of /bin/ls" + + sleep 10 +done Index: src/crypto/openssh/regress/keyscan.sh =================================================================== RCS file: src/crypto/openssh/regress/keyscan.sh diff -N src/crypto/openssh/regress/keyscan.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/keyscan.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,19 @@ +# $OpenBSD: keyscan.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="keyscan" + +# remove DSA hostkey +rm -f ${OBJ}/host.dsa + +start_sshd + +for t in rsa1 rsa dsa; do + trace "keyscan type $t" + ${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ + > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then + fail "ssh-keyscan -t $t failed with: $r" + fi +done Index: src/crypto/openssh/regress/proto-mismatch.sh =================================================================== RCS file: src/crypto/openssh/regress/proto-mismatch.sh diff -N src/crypto/openssh/regress/proto-mismatch.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/proto-mismatch.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,19 @@ +# $OpenBSD: proto-mismatch.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="protocol version mismatch" + +mismatch () +{ + server=$1 + client=$2 + banner=`echo ${client} | ${SSHD} -o "Protocol=${server}" -i -f ${OBJ}/sshd_proxy` + r=$? + trace "sshd prints ${banner}" + if [ $r -ne 255 ]; then + fail "sshd prints ${banner} and accepts connect with version ${client}" + fi +} + +mismatch 2 SSH-1.5-HALLO +mismatch 1 SSH-2.0-HALLO Index: src/crypto/openssh/regress/proto-version.sh =================================================================== RCS file: src/crypto/openssh/regress/proto-version.sh diff -N src/crypto/openssh/regress/proto-version.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/proto-version.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,34 @@ +# $OpenBSD: proto-version.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="sshd version with different protocol combinations" + +# we just start sshd in inetd mode and check the banner +check_version () +{ + version=$1 + expect=$2 + banner=`echo -n | ${SSHD} -o "Protocol=${version}" -i -f ${OBJ}/sshd_proxy` + case ${banner} in + SSH-1.99-*) + proto=199 + ;; + SSH-2.0-*) + proto=20 + ;; + SSH-1.5-*) + proto=15 + ;; + *) + proto=0 + ;; + esac + if [ ${expect} -ne ${proto} ]; then + fail "wrong protocol version ${banner} for ${version}" + fi +} + +check_version 2,1 199 +check_version 1,2 199 +check_version 2 20 +check_version 1 15 Index: src/crypto/openssh/regress/proxy-connect.sh =================================================================== RCS file: src/crypto/openssh/regress/proxy-connect.sh diff -N src/crypto/openssh/regress/proxy-connect.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/proxy-connect.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,11 @@ +# $OpenBSD: proxy-connect.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="proxy connect" + +for p in 1 2; do + ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true + if [ $? -ne 0 ]; then + fail "ssh proxyconnect protocol $p failed" + fi +done Index: src/crypto/openssh/regress/rsa_openssh.prv =================================================================== RCS file: src/crypto/openssh/regress/rsa_openssh.prv diff -N src/crypto/openssh/regress/rsa_openssh.prv --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/rsa_openssh.prv 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWgIBAAKBgQDsilwKcaKN6wSMNd1WgQ9+HRqQEkD0kCTVttrazGu0OhBU3Uko ++dFD1Ip0CxdXmN25JQWxOYF7h/Ocu8P3jzv3RTX87xKR0YzlXTLX+SLtF/ySebS3 +xWPrlfRUDhh03hR5V+8xxvvy9widPYKw/oItwGSueOsEq1LTczCDv2dAjQIDAQAB +An8nH5VzvHkMbSqJ6eOYDsVwomRvYbH5IEaYl1x6VATITNvAu9kUdQ4NsSpuMc+7 +Jj9gKZvmO1y2YCKc0P/iO+i/eV0L+yQh1Rw18jQZll+12T+LZrKRav03YNvMx0gN +wqWY48Kt6hv2/N/ebQzKRe79+D0t2cTh92hT7xENFLIBAkEBGnoGKFjAUkJCwO1V +mzpUqMHpRZVOrqP9hUmPjzNJ5oBPFGe4+h1hoSRFOAzaNuZt8ssbqaLCkzB8bfzj +qhZqAQJBANZekuUpp8iBLeLSagw5FkcPwPzq6zfExbhvsZXb8Bo/4SflNs4JHXwI +7SD9Z8aJLvM4uQ/5M70lblDMQ40i3o0CQQDIJvBYBFL5tlOgakq/O7yi+wt0L5BZ +9H79w5rCSAA0IHRoK/qI1urHiHC3f3vbbLk5UStfrqEaND/mm0shyNIBAkBLsYdC +/ctt5Bc0wUGK4Vl5bBmj9LtrrMJ4FpBpLwj/69BwCuKoK9XKZ0h73p6XHveCEGRg +PIlFX4MtaoLrwgU9AkBV2k4dgIws+X8YX65EsyyFjnlDqX4x0nSOjQB1msIKfHBr +dh5XLDBTTCxnKhMJ0Yx/opgOvf09XHBFwaQntR5i +-----END RSA PRIVATE KEY----- Index: src/crypto/openssh/regress/rsa_openssh.pub =================================================================== RCS file: src/crypto/openssh/regress/rsa_openssh.pub diff -N src/crypto/openssh/regress/rsa_openssh.pub --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/rsa_openssh.pub 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDsilwKcaKN6wSMNd1WgQ9+HRqQEkD0kCTVttrazGu0OhBU3Uko+dFD1Ip0CxdXmN25JQWxOYF7h/Ocu8P3jzv3RTX87xKR0YzlXTLX+SLtF/ySebS3xWPrlfRUDhh03hR5V+8xxvvy9widPYKw/oItwGSueOsEq1LTczCDv2dAjQ== Index: src/crypto/openssh/regress/rsa_ssh2.prv =================================================================== RCS file: src/crypto/openssh/regress/rsa_ssh2.prv diff -N src/crypto/openssh/regress/rsa_ssh2.prv --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/rsa_ssh2.prv 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,16 @@ +---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ---- +Subject: ssh-keygen test +Comment: "1024-bit rsa, Sat Jun 23 2001 12:21:26 -0400" +P2/56wAAAi4AAAA3aWYtbW9kbntzaWdue3JzYS1wa2NzMS1zaGExfSxlbmNyeXB0e3JzYS +1wa2NzMXYyLW9hZXB9fQAAAARub25lAAAB3wAAAdsAAAARAQABAAAD9icflXO8eQxtKonp +45gOxXCiZG9hsfkgRpiXXHpUBMhM28C72RR1Dg2xKm4xz7smP2Apm+Y7XLZgIpzQ/+I76L +95XQv7JCHVHDXyNBmWX7XZP4tmspFq/Tdg28zHSA3CpZjjwq3qG/b8395tDMpF7v34PS3Z +xOH3aFPvEQ0UsgEAAAQA7IpcCnGijesEjDXdVoEPfh0akBJA9JAk1bba2sxrtDoQVN1JKP +nRQ9SKdAsXV5jduSUFsTmBe4fznLvD948790U1/O8SkdGM5V0y1/ki7Rf8knm0t8Vj65X0 +VA4YdN4UeVfvMcb78vcInT2CsP6CLcBkrnjrBKtS03Mwg79nQI0AAAH/VdpOHYCMLPl/GF ++uRLMshY55Q6l+MdJ0jo0AdZrCCnxwa3YeVywwU0wsZyoTCdGMf6KYDr39PVxwRcGkJ7Ue +YgAAAgDWXpLlKafIgS3i0moMORZHD8D86us3xMW4b7GV2/AaP+En5TbOCR18CO0g/WfGiS +7zOLkP+TO9JW5QzEONIt6NAAACAQEaegYoWMBSQkLA7VWbOlSowelFlU6uo/2FSY+PM0nm +gE8UZ7j6HWGhJEU4DNo25m3yyxuposKTMHxt/OOqFmoB +---- END SSH2 ENCRYPTED PRIVATE KEY ---- +--- Index: src/crypto/openssh/regress/runtests.sh =================================================================== RCS file: src/crypto/openssh/regress/runtests.sh diff -N src/crypto/openssh/regress/runtests.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/runtests.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,13 @@ +#!/bin/sh + +TEST_SSH_SSH=../ssh +TEST_SSH_SSHD=../sshd +TEST_SSH_SSHAGENT=../ssh-agent +TEST_SSH_SSHADD=../ssh-add +TEST_SSH_SSHKEYGEN=../ssh-keygen +TEST_SSH_SSHKEYSCAN=../ssh-keyscan +TEST_SSH_SFTP=../sftp +TEST_SSH_SFTPSERVER=../sftp-server + +pmake + Index: src/crypto/openssh/regress/sftp.sh =================================================================== RCS file: src/crypto/openssh/regress/sftp.sh diff -N src/crypto/openssh/regress/sftp.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/sftp.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,29 @@ +# $OpenBSD: sftp.sh,v 1.2 2002/03/27 22:39:52 markus Exp $ +# Placed in the Public Domain. + +tid="basic sftp put/get" + +DATA=/bin/ls +COPY=${OBJ}/copy + +BUFFERSIZE="5 1000 32000 64000" +REQUESTS="1 2 10" + +for B in ${BUFFERSIZE}; do + for R in ${REQUESTS}; do + verbose "test $tid: buffer_size $B num_requests $R" + rm -f ${COPY}.1 ${COPY}.2 + ${SFTP} -P ${SFTPSERVER} -B $B -R $R -b /dev/stdin \ + > /dev/null 2>&1 << EOF + version + get $DATA ${COPY}.1 + put $DATA ${COPY}.2 +EOF + r=$? + if [ $r -ne 0 ]; then + fail "sftp failed with $r" + fi + cmp $DATA ${COPY}.1 || fail "corrupted copy after get" + cmp $DATA ${COPY}.2 || fail "corrupted copy after put" + done +done Index: src/crypto/openssh/regress/ssh-com-client.sh =================================================================== RCS file: src/crypto/openssh/regress/ssh-com-client.sh diff -N src/crypto/openssh/regress/ssh-com-client.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/ssh-com-client.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,127 @@ +# $OpenBSD: ssh-com-client.sh,v 1.3 2002/04/10 08:45:30 markus Exp $ +# Placed in the Public Domain. + +tid="connect with ssh.com client" + +#TEST_COMBASE=/path/to/ssh/com/binaries +if [ "X${TEST_COMBASE}" = "X" ]; then + fatal '$TEST_COMBASE is not set' +fi + +VERSIONS=" + 2.1.0 + 2.2.0 + 2.3.0 + 2.3.1 + 2.4.0 + 3.0.0 + 3.1.0" + +# 2.0.10 2.0.12 2.0.13 don't like the test setup + +# setup authorized keys +SRC=`dirname ${SCRIPT}` +cp ${SRC}/dsa_ssh2.prv ${OBJ}/id.com +chmod 600 ${OBJ}/id.com +${SSHKEYGEN} -i -f ${OBJ}/id.com > $OBJ/id.openssh +chmod 600 ${OBJ}/id.openssh +${SSHKEYGEN} -y -f ${OBJ}/id.openssh > $OBJ/authorized_keys_$USER +${SSHKEYGEN} -e -f ${OBJ}/id.openssh > $OBJ/id.com.pub +echo IdKey ${OBJ}/id.com > ${OBJ}/id.list + +# we need a DSA host key +t=dsa +rm -f ${OBJ}/$t ${OBJ}/$t.pub +${SSHKEYGEN} -q -N '' -t $t -f ${OBJ}/$t +$SUDO cp $OBJ/$t $OBJ/host.$t +echo HostKey $OBJ/host.$t >> $OBJ/sshd_config + +# add hostkeys to known hosts +mkdir -p ${OBJ}/${USER}/hostkeys +HK=${OBJ}/${USER}/hostkeys/key_${PORT}_127.0.0.1 +${SSHKEYGEN} -e -f ${OBJ}/rsa.pub > ${HK}.ssh-rsa.pub +${SSHKEYGEN} -e -f ${OBJ}/dsa.pub > ${HK}.ssh-dss.pub + +cat > ${OBJ}/ssh2_config << EOF +*: + QuietMode yes + StrictHostKeyChecking yes + Port ${PORT} + User ${USER} + Host 127.0.0.1 + IdentityFile ${OBJ}/id.list + RandomSeedFile ${OBJ}/random_seed + UserConfigDirectory ${OBJ}/%U + AuthenticationSuccessMsg no + BatchMode yes + ForwardX11 no +EOF + +# we need a real server (no ProxyConnect option) +start_sshd + +DATA=/bin/ls +COPY=${OBJ}/copy +rm -f ${COPY} + +# go for it +for v in ${VERSIONS}; do + ssh2=${TEST_COMBASE}/${v}/ssh2 + if [ ! -x ${ssh2} ]; then + continue + fi + verbose "ssh2 ${v}" + key=ssh-dss + skipcat=0 + case $v in + 2.1.*|2.3.0) + skipcat=1 + ;; + 3.0.*) + key=ssh-rsa + ;; + esac + cp ${HK}.$key.pub ${HK}.pub + + # check exit status + ${ssh2} -q -F ${OBJ}/ssh2_config somehost exit 42 + r=$? + if [ $r -ne 42 ]; then + fail "ssh2 ${v} exit code test failed (got $r, expected 42)" + fi + + # data transfer + rm -f ${COPY} + ${ssh2} -F ${OBJ}/ssh2_config somehost cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh2 ${v} cat test (receive) failed" + fi + cmp ${DATA} ${COPY} || fail "ssh2 ${v} cat test (receive) data mismatch" + + # data transfer, again + if [ $skipcat -eq 0 ]; then + rm -f ${COPY} + cat ${DATA} | \ + ${ssh2} -F ${OBJ}/ssh2_config host "cat > ${COPY}" + if [ $? -ne 0 ]; then + fail "ssh2 ${v} cat test (send) failed" + fi + cmp ${DATA} ${COPY} || \ + fail "ssh2 ${v} cat test (send) data mismatch" + fi + + # no stderr after eof + rm -f ${COPY} + ${ssh2} -F ${OBJ}/ssh2_config somehost \ + exec sh -c \'"exec > /dev/null; sleep 1; echo bla 1>&2; exit 0"\' \ + 2> /dev/null + if [ $? -ne 0 ]; then + fail "ssh2 ${v} stderr test failed" + fi +done + +rm -rf ${OBJ}/${USER} +for i in ssh2_config random_seed dsa.pub dsa host.dsa \ + id.list id.com id.com.pub id.openssh; do + rm -f ${OBJ}/$i +done Index: src/crypto/openssh/regress/ssh-com-keygen.sh =================================================================== RCS file: src/crypto/openssh/regress/ssh-com-keygen.sh diff -N src/crypto/openssh/regress/ssh-com-keygen.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/ssh-com-keygen.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,67 @@ +# $OpenBSD: ssh-com-keygen.sh,v 1.1 2002/03/27 22:40:27 markus Exp $ +# Placed in the Public Domain. + +tid="ssh.com key import" + +#TEST_COMBASE=/path/to/ssh/com/binaries +if [ "X${TEST_COMBASE}" = "X" ]; then + fatal '$TEST_COMBASE is not set' +fi + +VERSIONS=" + 2.0.10 + 2.0.12 + 2.0.13 + 2.1.0 + 2.2.0 + 2.3.0 + 2.3.1 + 2.4.0 + 3.0.0 + 3.1.0" + +COMPRV=${OBJ}/comkey +COMPUB=${COMPRV}.pub +OPENSSHPRV=${OBJ}/opensshkey +OPENSSHPUB=${OPENSSHPRV}.pub + +# go for it +for v in ${VERSIONS}; do + keygen=${TEST_COMBASE}/${v}/ssh-keygen2 + if [ ! -x ${keygen} ]; then + continue + fi + types="dss" + case $v in + 2.3.1|3.*) + types="$types rsa" + ;; + esac + for t in $types; do + verbose "ssh-keygen $v/$t" + rm -f $COMPRV $COMPUB $OPENSSHPRV $OPENSSHPUB + ${keygen} -q -P -t $t ${COMPRV} > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "${keygen} -t $t failed" + continue + fi + ${SSHKEYGEN} -if ${COMPUB} > ${OPENSSHPUB} + if [ $? -ne 0 ]; then + fail "import public key ($v/$t) failed" + continue + fi + ${SSHKEYGEN} -if ${COMPRV} > ${OPENSSHPRV} + if [ $? -ne 0 ]; then + fail "import private key ($v/$t) failed" + continue + fi + chmod 600 ${OPENSSHPRV} + ${SSHKEYGEN} -yf ${OPENSSHPRV} |\ + diff - ${OPENSSHPUB} + if [ $? -ne 0 ]; then + fail "public keys ($v/$t) differ" + fi + done +done + +rm -f $COMPRV $COMPUB $OPENSSHPRV $OPENSSHPUB Index: src/crypto/openssh/regress/ssh-com-sftp.sh =================================================================== RCS file: src/crypto/openssh/regress/ssh-com-sftp.sh diff -N src/crypto/openssh/regress/ssh-com-sftp.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/ssh-com-sftp.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,54 @@ +# $OpenBSD: ssh-com-sftp.sh,v 1.2 2002/04/10 08:45:30 markus Exp $ +# Placed in the Public Domain. + +tid="basic sftp put/get with ssh.com server" + +DATA=/bin/ls +COPY=${OBJ}/copy + +BUFFERSIZE="5 1000 32000 64000" +REQUESTS="1 2 10" + +#TEST_COMBASE=/path/to/ssh/com/binaries +if [ "X${TEST_COMBASE}" = "X" ]; then + fatal '$TEST_COMBASE is not set' +fi + +VERSIONS=" + 2.0.10 + 2.0.12 + 2.0.13 + 2.1.0 + 2.2.0 + 2.3.0 + 2.3.1 + 2.4.0 + 3.0.0 + 3.1.0" + +# go for it +for v in ${VERSIONS}; do + server=${TEST_COMBASE}/${v}/sftp-server2 + if [ ! -x ${server} ]; then + continue + fi + verbose "sftp-server $v" + for B in ${BUFFERSIZE}; do + for R in ${REQUESTS}; do + verbose "test $tid: buffer_size $B num_requests $R" + rm -f ${COPY}.1 ${COPY}.2 + ${SFTP} -P ${server} -B $B -R $R -b /dev/stdin \ + > /dev/null 2>&1 << EOF + version + get $DATA ${COPY}.1 + put $DATA ${COPY}.2 +EOF + r=$? + if [ $r -ne 0 ]; then + fail "sftp failed with $r" + fi + cmp $DATA ${COPY}.1 || fail "corrupted copy after get" + cmp $DATA ${COPY}.2 || fail "corrupted copy after put" + done + done +done Index: src/crypto/openssh/regress/ssh-com.sh =================================================================== RCS file: src/crypto/openssh/regress/ssh-com.sh diff -N src/crypto/openssh/regress/ssh-com.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/ssh-com.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,112 @@ +# $OpenBSD: ssh-com.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="connect to ssh.com server" + +#TEST_COMBASE=/path/to/ssh/com/binaries +if [ "X${TEST_COMBASE}" = "X" ]; then + fatal '$TEST_COMBASE is not set' +fi + +VERSIONS=" + 2.0.12 + 2.0.13 + 2.1.0 + 2.2.0 + 2.3.0 + 2.3.1 + 2.4.0 + 3.0.0 + 3.1.0" +# 2.0.10 does not support UserConfigDirectory + +SRC=`dirname ${SCRIPT}` + +# ssh.com +cat << EOF > $OBJ/sshd2_config +*: + # Port and ListenAdress are not used. + QuietMode yes + Port 4343 + ListenAddress 127.0.0.1 + UserConfigDirectory ${OBJ}/%U + Ciphers AnyCipher + PubKeyAuthentication yes + #AllowedAuthentications publickey + AuthorizationFile authorization + HostKeyFile ${SRC}/dsa_ssh2.prv + PublicHostKeyFile ${SRC}/dsa_ssh2.pub + RandomSeedFile ${OBJ}/random_seed + MaxConnections 0 + PermitRootLogin yes + VerboseMode no + CheckMail no + Ssh1Compatibility no +EOF + +# create client config +sed "s/HostKeyAlias.*/HostKeyAlias ssh2-localhost-with-alias/" \ + < $OBJ/ssh_config > $OBJ/ssh_config_com + +# we need a DSA key for +rm -f ${OBJ}/dsa ${OBJ}/dsa.pub +${SSHKEYGEN} -q -N '' -t dsa -f ${OBJ}/dsa + +# setup userdir, try rsa first +mkdir -p ${OBJ}/${USER} +cp /dev/null ${OBJ}/${USER}/authorization +for t in rsa dsa; do + ${SSHKEYGEN} -e -f ${OBJ}/$t.pub > ${OBJ}/${USER}/$t.com + echo Key $t.com >> ${OBJ}/${USER}/authorization + echo IdentityFile ${OBJ}/$t >> ${OBJ}/ssh_config_com +done + +# convert and append DSA hostkey +( + echo -n 'ssh2-localhost-with-alias,127.0.0.1,::1 ' + ${SSHKEYGEN} -if ${SRC}/dsa_ssh2.pub +) >> $OBJ/known_hosts + +# go for it +for v in ${VERSIONS}; do + sshd2=${TEST_COMBASE}/${v}/sshd2 + if [ ! -x ${sshd2} ]; then + continue + fi + trace "sshd2 ${v}" + PROXY="proxycommand ${sshd2} -qif ${OBJ}/sshd2_config 2> /dev/null" + ${SSH} -qF ${OBJ}/ssh_config_com -o "${PROXY}" dummy exit 0 + if [ $? -ne 0 ]; then + fail "ssh connect to sshd2 ${v} failed" + fi + + ciphers="3des-cbc blowfish-cbc arcfour" + macs="hmac-md5" + case $v in + 2.4.*) + ciphers="$ciphers cast128-cbc" + macs="$macs hmac-sha1 hmac-sha1-96 hmac-md5-96" + ;; + 3.*) + ciphers="$ciphers aes128-cbc cast128-cbc" + macs="$macs hmac-sha1 hmac-sha1-96 hmac-md5-96" + ;; + esac + #ciphers="3des-cbc" + for m in $macs; do + for c in $ciphers; do + trace "sshd2 ${v} cipher $c mac $m" + verbose "test ${tid}: sshd2 ${v} cipher $c mac $m" + ${SSH} -c $c -m $m -qF ${OBJ}/ssh_config_com -o "${PROXY}" dummy exit 0 + if [ $? -ne 0 ]; then + fail "ssh connect to sshd2 ${v} with $c/$m failed" + fi + done + done +done + +rm -rf ${OBJ}/${USER} +for i in sshd_config_proxy ssh_config_proxy random_seed \ + sshd2_config dsa.pub dsa ssh_config_com; do + rm -f ${OBJ}/$i +done Index: src/crypto/openssh/regress/stderr-after-eof.sh =================================================================== RCS file: src/crypto/openssh/regress/stderr-after-eof.sh diff -N src/crypto/openssh/regress/stderr-after-eof.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/stderr-after-eof.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,30 @@ +# $OpenBSD: stderr-after-eof.sh,v 1.1 2002/03/23 16:38:09 markus Exp $ +# Placed in the Public Domain. + +tid="stderr data after eof" + +DATA=/etc/motd +DATA=${OBJ}/data +COPY=${OBJ}/copy + +MD5=md5sum + +# setup data +rm -f ${DATA} ${COPY} +cp /dev/null ${DATA} +for i in 1 2 3 4 5 6; do + (date;echo $i) | $MD5 >> ${DATA} +done + +${SSH} -2 -F $OBJ/ssh_proxy otherhost \ + exec sh -c \'"exec > /dev/null; sleep 2; cat ${DATA} 1>&2 $s"\' \ + 2> ${COPY} +r=$? +if [ $r -ne 0 ]; then + fail "ssh failed with exit code $r" +fi +egrep 'Disconnecting: Received extended_data after EOF' ${COPY} && + fail "ext data received after eof" +cmp ${DATA} ${COPY} || fail "stderr corrupt" + +rm -f ${DATA} ${COPY} Index: src/crypto/openssh/regress/stderr-data.sh =================================================================== RCS file: src/crypto/openssh/regress/stderr-data.sh diff -N src/crypto/openssh/regress/stderr-data.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/stderr-data.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,33 @@ +# $OpenBSD: stderr-data.sh,v 1.2 2002/03/27 22:39:52 markus Exp $ +# Placed in the Public Domain. + +tid="stderr data transfer" + +DATA=/bin/ls +COPY=${OBJ}/copy +rm -f ${COPY} + +for n in '' -n; do +for p in 1 2; do + verbose "test $tid: proto $p ($n)" + ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \ + exec sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ + 2> ${COPY} + r=$? + if [ $r -ne 0 ]; then + fail "ssh failed with exit code $r" + fi + cmp ${DATA} ${COPY} || fail "stderr corrupt" + rm -f ${COPY} + + ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \ + exec sh -c \'"echo a; exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ + > /dev/null 2> ${COPY} + r=$? + if [ $r -ne 0 ]; then + fail "ssh failed with exit code $r" + fi + cmp ${DATA} ${COPY} || fail "stderr corrupt" + rm -f ${COPY} +done +done Index: src/crypto/openssh/regress/t4.ok =================================================================== RCS file: src/crypto/openssh/regress/t4.ok diff -N src/crypto/openssh/regress/t4.ok --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/t4.ok 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1 @@ +3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36 Index: src/crypto/openssh/regress/t5.ok =================================================================== RCS file: src/crypto/openssh/regress/t5.ok diff -N src/crypto/openssh/regress/t5.ok --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/t5.ok 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1 @@ +xokes-lylis-byleh-zebib-kalus-bihas-tevah-haroz-suhar-foved-noxex Index: src/crypto/openssh/regress/test-exec.sh =================================================================== RCS file: src/crypto/openssh/regress/test-exec.sh diff -N src/crypto/openssh/regress/test-exec.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/test-exec.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,224 @@ +# $OpenBSD: test-exec.sh,v 1.14 2002/04/15 15:19:48 markus Exp $ +# Placed in the Public Domain. + +PORT=4242 +USER=`id -un` +SUDO= +#SUDO=sudo + +OBJ=$1 +if [ "x$OBJ" = "x" ]; then + echo '$OBJ not defined' + exit 2 +fi +if [ ! -d $OBJ ]; then + echo "not a directory: $OBJ" + exit 2 +fi +SCRIPT=$2 +if [ "x$SCRIPT" = "x" ]; then + echo '$SCRIPT not defined' + exit 2 +fi +if [ ! -f $SCRIPT ]; then + echo "not a file: $SCRIPT" + exit 2 +fi +if sh -n $SCRIPT; then + true +else + echo "syntax error in $SCRIPT" + exit 2 +fi +unset SSH_AUTH_SOCK + +# defaults +SSH=ssh +SSHD=sshd +SSHAGENT=ssh-agent +SSHADD=ssh-add +SSHKEYGEN=ssh-keygen +SSHKEYSCAN=ssh-keyscan +SFTP=sftp +SFTPSERVER=/usr/libexec/openssh/sftp-server + +if [ "x$TEST_SSH_SSH" != "x" ]; then + SSH=${TEST_SSH_SSH} +fi +if [ "x$TEST_SSH_SSHD" != "x" ]; then + SSHD=${TEST_SSH_SSHD} +fi +if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then + SSHAGENT=${TEST_SSH_SSHAGENT} +fi +if [ "x$TEST_SSH_SSHADD" != "x" ]; then + SSHADD=${TEST_SSH_SSHADD} +fi +if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then + SSHKEYGEN=${TEST_SSH_SSHKEYGEN} +fi +if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then + SSHKEYSCAN=${TEST_SSH_SSHKEYSCAN} +fi +if [ "x$TEST_SSH_SFTP" != "x" ]; then + SFTP=${TEST_SSH_SFTP} +fi +if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then + SFTPSERVER=${TEST_SSH_SFTPSERVER} +fi + +# these should be used in tests +export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER +#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER + +# helper +cleanup () +{ + if [ -f $PIDFILE ]; then + pid=`cat $PIDFILE` + if [ "X$pid" = "X" ]; then + echo no sshd running + else + if [ $pid -lt 2 ]; then + echo bad pid for ssd: $pid + else + $SUDO kill $pid + fi + fi + fi +} + +trace () +{ + if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then + echo "$@" + fi +} + +verbose () +{ + if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then + echo "$@" + fi +} + + +fail () +{ + RESULT=1 + echo "$@" +} + +fatal () +{ + echo -n "FATAL: " + fail "$@" + cleanup + exit $RESULT +} + +RESULT=0 +PIDFILE=$OBJ/pidfile + +trap fatal 3 2 + +# create server config +cat << EOF > $OBJ/sshd_config + Port $PORT + ListenAddress 127.0.0.1 + #ListenAddress ::1 + PidFile $PIDFILE + AuthorizedKeysFile $OBJ/authorized_keys_%u + LogLevel QUIET +EOF + +# server config for proxy connects +cp $OBJ/sshd_config $OBJ/sshd_proxy + +# allow group-writable directories in proxy-mode +echo 'StrictModes no' >> $OBJ/sshd_proxy + +# create client config +cat << EOF > $OBJ/ssh_config +Host * + Hostname 127.0.0.1 + HostKeyAlias localhost-with-alias + Port $PORT + User $USER + GlobalKnownHostsFile $OBJ/known_hosts + UserKnownHostsFile $OBJ/known_hosts + RSAAuthentication yes + PubkeyAuthentication yes + ChallengeResponseAuthentication no + HostbasedAuthentication no + PasswordAuthentication no + RhostsAuthentication no + RhostsRSAAuthentication no + BatchMode yes + StrictHostKeyChecking yes +EOF + +rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER + +trace "generate keys" +for t in rsa rsa1; do + # generate user key + rm -f $OBJ/$t + ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ + fail "ssh-keygen for $t failed" + + # known hosts file for client + ( + echo -n 'localhost-with-alias,127.0.0.1,::1 ' + cat $OBJ/$t.pub + ) >> $OBJ/known_hosts + + # setup authorized keys + cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER + echo IdentityFile $OBJ/$t >> $OBJ/ssh_config + + # use key as host key, too + $SUDO cp $OBJ/$t $OBJ/host.$t + echo HostKey $OBJ/host.$t >> $OBJ/sshd_config + + # don't use SUDO for proxy connect + echo HostKey $OBJ/$t >> $OBJ/sshd_proxy +done +chmod 644 $OBJ/authorized_keys_$USER + +# create a proxy version of the client config +( + cat $OBJ/ssh_config + echo proxycommand ${SSHD} -i -f $OBJ/sshd_proxy +) > $OBJ/ssh_proxy + +# check proxy config +${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" + +start_sshd () +{ + # start sshd + $SUDO ${SSHD} -f $OBJ/sshd_config -t || fatal "sshd_config broken" + $SUDO ${SSHD} -f $OBJ/sshd_config + + trace "wait for sshd" + i=0; + while [ ! -f $PIDFILE -a $i -lt 5 ]; do + i=`expr $i + 1` + sleep $i + done + + test -f $PIDFILE || fatal "no sshd running on port $PORT" +} + +# source test body +. $SCRIPT + +# kill sshd +cleanup +if [ $RESULT -eq 0 ]; then + verbose ok $tid +else + echo failed $tid +fi +exit $RESULT Index: src/crypto/openssh/regress/transfer.sh =================================================================== RCS file: src/crypto/openssh/regress/transfer.sh diff -N src/crypto/openssh/regress/transfer.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/transfer.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,29 @@ +# $OpenBSD: transfer.sh,v 1.1 2002/03/27 00:03:37 markus Exp $ +# Placed in the Public Domain. + +tid="transfer data" + +DATA=/bin/ls +COPY=${OBJ}/copy + +for p in 1 2; do + verbose "$tid: proto $p" + rm -f ${COPY} + ${SSH} -n -q -$p -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" + + for s in 10 100 1k 32k 64k 128k 256k; do + trace "proto $p dd-size ${s}" + rm -f ${COPY} + dd if=$DATA obs=${s} 2> /dev/null | \ + ${SSH} -q -$p -F $OBJ/ssh_proxy somehost "cat > ${COPY}" + if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" + fi + cmp $DATA ${COPY} || fail "corrupted copy" + done +done +rm -f ${COPY} Index: src/crypto/openssh/regress/try-ciphers.sh =================================================================== RCS file: src/crypto/openssh/regress/try-ciphers.sh diff -N src/crypto/openssh/regress/try-ciphers.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/try-ciphers.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,29 @@ +# $OpenBSD: try-ciphers.sh,v 1.7 2002/04/03 09:30:01 markus Exp $ +# Placed in the Public Domain. + +tid="try ciphers" + +ciphers="aes128-cbc 3des-cbc blowfish-cbc cast128-cbc arcfour + aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se" +macs="hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96" + +for c in $ciphers; do + for m in $macs; do + trace "proto 2 cipher $c mac $m" + verbose "test $tid: proto 2 cipher $c mac $m" + ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true + if [ $? -ne 0 ]; then + fail "ssh -2 failed with mac $m cipher $c" + fi + done +done + +ciphers="3des blowfish" +for c in $ciphers; do + trace "proto 1 cipher $c" + verbose "test $tid: proto 1 cipher $c" + ${SSH} -F $OBJ/ssh_proxy -1 -c $c somehost true + if [ $? -ne 0 ]; then + fail "ssh -1 failed with cipher $c" + fi +done Index: src/crypto/openssh/regress/yes-head.sh =================================================================== RCS file: src/crypto/openssh/regress/yes-head.sh diff -N src/crypto/openssh/regress/yes-head.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/regress/yes-head.sh 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,15 @@ +# $OpenBSD: yes-head.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# Placed in the Public Domain. + +tid="yes pipe head" + +for p in 1 2; do + lines=`${SSH} -$p -F $OBJ/ssh_proxy thishost 'yes | head -2000' | (sleep 3 ; wc -l)` + if [ $? -ne 0 ]; then + fail "yes|head test failed" + lines = 0; + fi + if [ $lines -ne 2000 ]; then + fail "yes|head returns $lines lines instead of 2000" + fi +done Index: src/crypto/openssh/scard/Makefile.in =================================================================== RCS file: src/crypto/openssh/scard/Makefile.in diff -N src/crypto/openssh/scard/Makefile.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/scard/Makefile.in 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,28 @@ +# $Id$ + +prefix=@prefix@ +datadir=@datadir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ + +INSTALL=@INSTALL@ + +VPATH=@srcdir@ + +all: + +#Ssh.bin: Ssh.bin.uu +# uudecode Ssh.bin.uu + +clean: +# rm -rf Ssh.bin + +distprep: + uudecode Ssh.bin.uu + +distclean: clean + rm -f Makefile *~ + +install: $(srcdir)/Ssh.bin + $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir) + $(INSTALL) -m 0644 $(srcdir)/Ssh.bin $(DESTDIR)$(datadir)/Ssh.bin Index: src/crypto/openssh/scard/Ssh.bin =================================================================== RCS file: src/crypto/openssh/scard/Ssh.bin diff -N src/crypto/openssh/scard/Ssh.bin Binary files /dev/null and Ssh.bin differ Index: src/crypto/openssh/scard/Ssh.bin.uu =================================================================== RCS file: src/crypto/openssh/scard/Ssh.bin.uu diff -N src/crypto/openssh/scard/Ssh.bin.uu --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/scard/Ssh.bin.uu 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,17 @@ +begin 644 Ssh.bin +M`P)!&P`801X`>``!`E@"`/Y@\`4`_J'P!0!!&T$=`?Z@\`4`01M!'`'^>/,! +M`4$;01X!_G#S%P'^0],1`?Y@\!0`_G/S'0#^<]4``D$;L`4`_F'3``#^8=,% +M`/ZAT`$!_J#0)P'^H],*`?ZCTPD`_G/5"P7^8=,'`OZAT`H`_J#0$@3^:-,@ +M`T$;`P`%`/Y@`\A```/`0__(%`@8!`0H``&`` +M0205!!D)I$L`"0J0`&``*!4$&58``````.P````%____P````.D````0```` +M,P```"````#'````,````(T````R````V!4#&0A*``D*;@!@`"@5!QD*`/\] +M(6``1A)*``D*9P!@`"@*/P!@`$LK"1)@`$LK!6``4!P$#00#2@`.#01@`%5@ +M`%I@`"@37``>%0@2%0A>`%\($F``9%(`:`H_`&``2RL*7@`R10`/$UP`'@H`R`D07@`W!%>P!?_R`0$$`@`\```37P`` +M$V+^H2U?``5=``H38OZ@+5\`#UT`%!-B_G@M"@0`7P`970`>"@0`8``C10`) +/"F<`8``H$UX`+5D````` +` +end Index: src/crypto/openssh/scard/Ssh.java =================================================================== RCS file: src/crypto/openssh/scard/Ssh.java diff -N src/crypto/openssh/scard/Ssh.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/crypto/openssh/scard/Ssh.java 30 Jun 2002 11:38:03 -0000 @@ -0,0 +1,164 @@ +// $Id$ +// +// Ssh.java +// SSH / smartcard integration project, smartcard side +// +// Tomoko Fukuzawa, created, Feb., 2000 +// +// Naomaru Itoi, modified, Apr., 2000 +// + +// copyright 2000 +// the regents of the university of michigan +// all rights reserved +// +// permission is granted to use, copy, create derivative works +// and redistribute this software and such derivative works +// for any purpose, so long as the name of the university of +// michigan is not used in any advertising or publicity +// pertaining to the use or distribution of this software +// without specific, written prior authorization. if the +// above copyright notice or any other identification of the +// university of michigan is included in any copy of any +// portion of this software, then the disclaimer below must +// also be included. +// +// this software is provided as is, without representation +// from the university of michigan as to its fitness for any +// purpose, and without warranty by the university of +// michigan of any kind, either express or implied, including +// without limitation the implied warranties of +// merchantability and fitness for a particular purpose. the +// regents of the university of michigan shall not be liable +// for any damages, including special, indirect, incidental, or +// consequential damages, with respect to any claim arising +// out of or in connection with the use of the software, even +// if it has been or is hereafter advised of the possibility of +// such damages. + +import javacard.framework.*; +import javacardx.framework.*; +import javacardx.crypto.*; + +public class Ssh extends javacard.framework.Applet +{ + // Change this when the applet changes; hi byte is major, low byte is minor + static final short applet_version = (short)0x0102; + + /* constants declaration */ + // code of CLA byte in the command APDU header + static final byte Ssh_CLA =(byte)0x05; + + // codes of INS byte in the command APDU header + static final byte DECRYPT = (byte) 0x10; + static final byte GET_KEYLENGTH = (byte) 0x20; + static final byte GET_PUBKEY = (byte) 0x30; + static final byte GET_VERSION = (byte) 0x32; + static final byte GET_RESPONSE = (byte) 0xc0; + + static final short keysize = 1024; + static final short root_fid = (short)0x3f00; + static final short privkey_fid = (short)0x0012; + static final short pubkey_fid = (short)(('s'<<8)|'h'); + + /* instance variables declaration */ + AsymKey rsakey; + CyberflexFile file; + CyberflexOS os; + + private Ssh() + { + file = new CyberflexFile(); + os = new CyberflexOS(); + + rsakey = new RSA_CRT_PrivateKey (keysize); + + if ( ! rsakey.isSupportedLength (keysize) ) + ISOException.throwIt (ISO.SW_WRONG_LENGTH); + + register(); + } // end of the constructor + + public boolean select() { + if (!rsakey.isInitialized()) + rsakey.setKeyInstance ((short)0xc8, (short)0x10); + + return true; + } + + public static void install(APDU apdu) + { + new Ssh(); // create a Ssh applet instance (card) + } // end of install method + + public static void main(String args[]) { + ISOException.throwIt((short) 0x9000); + } + + public void process(APDU apdu) + { + // APDU object carries a byte array (buffer) to + // transfer incoming and outgoing APDU header + // and data bytes between card and CAD + byte buffer[] = apdu.getBuffer(); + short size, st; + + // verify that if the applet can accept this + // APDU message + // NI: change suggested by Wayne Dyksen, Purdue + if (buffer[ISO.OFFSET_INS] == ISO.INS_SELECT) + ISOException.throwIt(ISO.SW_NO_ERROR); + + switch (buffer[ISO.OFFSET_INS]) { + case DECRYPT: + if (buffer[ISO.OFFSET_CLA] != Ssh_CLA) + ISOException.throwIt(ISO.SW_CLA_NOT_SUPPORTED); + //decrypt (apdu); + size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF); + + if (apdu.setIncomingAndReceive() != size) + ISOException.throwIt (ISO.SW_WRONG_LENGTH); + + // check access; depends on bit 2 (x/a) + file.selectFile(root_fid); + file.selectFile(privkey_fid); + st = os.checkAccess(ACL.EXECUTE); + if (st != ST.ACCESS_CLEARED) { + CyberflexAPDU.prepareSW1SW2(st); + ISOException.throwIt(CyberflexAPDU.getSW1SW2()); + } + + rsakey.cryptoUpdate (buffer, (short) ISO.OFFSET_CDATA, size, + buffer, (short) ISO.OFFSET_CDATA); + + apdu.setOutgoingAndSend ((short) ISO.OFFSET_CDATA, size); + break; + case GET_PUBKEY: + file.selectFile(root_fid); // select root + file.selectFile(pubkey_fid); // select public key file + size = (short)(file.getFileSize() - 16); + st = os.readBinaryFile(buffer, (short)0, (short)0, size); + if (st == ST.SUCCESS) + apdu.setOutgoingAndSend((short)0, size); + else { + CyberflexAPDU.prepareSW1SW2(st); + ISOException.throwIt(CyberflexAPDU.getSW1SW2()); + } + break; + case GET_KEYLENGTH: + Util.setShort(buffer, (short)0, keysize); + apdu.setOutgoingAndSend ((short)0, (short)2); + break; + case GET_VERSION: + Util.setShort(buffer, (short)0, applet_version); + apdu.setOutgoingAndSend ((short)0, (short)2); + break; + case GET_RESPONSE: + break; + default: + ISOException.throwIt (ISO.SW_INS_NOT_SUPPORTED); + } + + } // end of process method + +} // end of class Ssh Index: src/crypto/openssh/scp/Makefile =================================================================== RCS file: src/crypto/openssh/scp/Makefile diff -N src/crypto/openssh/scp/Makefile --- src/crypto/openssh/scp/Makefile 28 Sep 2001 01:33:50 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,15 +0,0 @@ -# $OpenBSD: Makefile,v 1.12 2001/04/16 02:31:48 mouring Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= scp -BINOWN= root - -BINMODE?=555 - -BINDIR= /usr/bin -MAN= scp.1 - -SRCS= scp.c scp-common.c - -.include Index: src/crypto/openssh/sftp-server/Makefile =================================================================== RCS file: src/crypto/openssh/sftp-server/Makefile diff -N src/crypto/openssh/sftp-server/Makefile --- src/crypto/openssh/sftp-server/Makefile 28 Sep 2001 01:33:50 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,18 +0,0 @@ -# $OpenBSD: Makefile,v 1.5 2001/03/03 23:59:36 markus Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= sftp-server -BINOWN= root - -BINMODE?=555 - -BINDIR= /usr/libexec -MAN= sftp-server.8 - -SRCS= sftp-server.c sftp-common.c - -.include - -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} Index: src/crypto/openssh/ssh/Makefile =================================================================== RCS file: src/crypto/openssh/ssh/Makefile diff -N src/crypto/openssh/ssh/Makefile --- src/crypto/openssh/ssh/Makefile 28 Sep 2001 01:33:50 -0000 1.1.1.1.2.3 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,34 +0,0 @@ -# $OpenBSD: Makefile,v 1.30 2001/04/14 16:33:20 stevesk Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= ssh -BINOWN= root - -BINMODE?=4555 - -BINDIR= /usr/bin -MAN= ssh.1 -LINKS= ${BINDIR}/ssh ${BINDIR}/slogin -MLINKS= ssh.1 slogin.1 - -SRCS= ssh.c readconf.c clientloop.c sshtty.c \ - sshconnect.c sshconnect1.c sshconnect2.c - -.include # for AFS - -.if (${KERBEROS:L} == "yes") -CFLAGS+= -DKRB4 -I${DESTDIR}/usr/include/kerberosIV -LDADD+= -lkrb -DPADD+= ${LIBKRB} -.if (${AFS:L} == "yes") -CFLAGS+= -DAFS -LDADD+= -lkafs -DPADD+= ${LIBKRBAFS} -.endif # AFS -.endif # KERBEROS - -.include - -LDADD+= -lcrypto -lz -DPADD+= ${LIBCRYPTO} ${LIBZ} Index: src/crypto/openssh/ssh-add/Makefile =================================================================== RCS file: src/crypto/openssh/ssh-add/Makefile diff -N src/crypto/openssh/ssh-add/Makefile --- src/crypto/openssh/ssh-add/Makefile 28 Sep 2001 01:33:50 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,18 +0,0 @@ -# $OpenBSD: Makefile,v 1.20 2001/03/04 00:51:25 markus Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= ssh-add -BINOWN= root - -BINMODE?=555 - -BINDIR= /usr/bin -MAN= ssh-add.1 - -SRCS= ssh-add.c - -.include - -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} Index: src/crypto/openssh/ssh-agent/Makefile =================================================================== RCS file: src/crypto/openssh/ssh-agent/Makefile diff -N src/crypto/openssh/ssh-agent/Makefile --- src/crypto/openssh/ssh-agent/Makefile 28 Sep 2001 01:33:50 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,18 +0,0 @@ -# $OpenBSD: Makefile,v 1.17 2001/03/04 00:51:25 markus Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= ssh-agent -BINOWN= root - -BINMODE?=555 - -BINDIR= /usr/bin -MAN= ssh-agent.1 - -SRCS= ssh-agent.c - -.include - -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} Index: src/crypto/openssh/ssh-keygen/Makefile =================================================================== RCS file: src/crypto/openssh/ssh-keygen/Makefile diff -N src/crypto/openssh/ssh-keygen/Makefile --- src/crypto/openssh/ssh-keygen/Makefile 28 Sep 2001 01:33:50 -0000 1.1.1.1.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,18 +0,0 @@ -# $OpenBSD: Makefile,v 1.17 2001/03/04 00:51:26 markus Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= ssh-keygen -BINOWN= root - -BINMODE?=555 - -BINDIR= /usr/bin -MAN= ssh-keygen.1 - -SRCS= ssh-keygen.c - -.include - -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} Index: src/crypto/openssh/sshd/Makefile =================================================================== RCS file: src/crypto/openssh/sshd/Makefile diff -N src/crypto/openssh/sshd/Makefile --- src/crypto/openssh/sshd/Makefile 28 Sep 2001 01:33:51 -0000 1.1.1.1.2.4 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,46 +0,0 @@ -# $OpenBSD: Makefile,v 1.38 2001/03/29 21:17:40 markus Exp $ - -.PATH: ${.CURDIR}/.. - -PROG= sshd -BINOWN= root -BINMODE=555 -BINDIR= /usr/sbin -MAN= sshd.8 -CFLAGS+=-DHAVE_LOGIN_CAP - -SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \ - sshpty.c sshlogin.c servconf.c serverloop.c \ - auth.c auth1.c auth2.c auth-options.c session.c \ - auth-chall.c auth2-chall.c groupaccess.c - -.include # for KERBEROS and AFS - -.if (${KERBEROS:L} == "yes") -.if (${AFS:L} == "yes") -CFLAGS+= -DAFS -LDADD+= -lkafs -DPADD+= ${LIBKRBAFS} -.endif # AFS -CFLAGS+= -DKRB4 -I${DESTDIR}/usr/include/kerberosIV -SRCS+= auth-krb4.c -LDADD+= -lkrb -DPADD+= ${LIBKRB} -.endif # KERBEROS - -.include - -LDADD+= -lcrypto -lutil -lz -DPADD+= ${LIBCRYPTO} ${LIBUTIL} ${LIBZ} - -.if (${TCP_WRAPPERS:L} == "yes") -CFLAGS+= -DLIBWRAP -LDADD+= -lwrap -DPADD+= ${LIBWRAP} -.endif - -.if (${SKEY:L} == "yes") -CFLAGS+= -DSKEY -LDADD+= -lskey -DPADD+= ${SKEY} -.endif Index: src/etc/pam.conf =================================================================== RCS file: /home/ncvs/src/etc/Attic/pam.conf,v retrieving revision 1.6.2.13 diff -u -u -r1.6.2.13 pam.conf --- src/etc/pam.conf 19 Dec 2001 16:47:46 -0000 1.6.2.13 +++ src/etc/pam.conf 30 Jun 2002 16:29:33 -0000 @@ -44,6 +44,8 @@ # If the user can authenticate with S/Key, that's sufficient; allow clear # password. Try kerberos, then try plain unix password. login auth sufficient pam_skey.so +login auth sufficient pam_opie.so +login auth required pam_opieaccess.so login auth requisite pam_cleartext_pass_ok.so #login auth sufficient pam_kerberosIV.so try_first_pass login auth required pam_unix.so try_first_pass @@ -53,6 +55,8 @@ # Same requirement for ftpd as login ftpd auth sufficient pam_skey.so +ftpd auth sufficient pam_opie.so +ftpd auth required pam_opieaccess.so ftpd auth requisite pam_cleartext_pass_ok.so #ftpd auth sufficient pam_kerberosIV.so try_first_pass ftpd auth required pam_unix.so try_first_pass @@ -60,13 +64,14 @@ # OpenSSH with PAM support requires similar modules. The session one is # a bit strange, though... sshd auth sufficient pam_skey.so +sshd auth sufficient pam_opie.so +sshd auth required pam_opieaccess.so #sshd auth sufficient pam_kerberosIV.so try_first_pass +#sshd auth sufficient pam_krb5.so try_first_pass sshd auth required pam_unix.so try_first_pass sshd account required pam_unix.so sshd password required pam_permit.so sshd session required pam_permit.so -# "csshd" is for challenge-based authentication with sshd (TIS auth, etc.) -csshd auth required pam_skey.so # "telnetd" is for SRA authenticated telnet only. Non-SRA uses 'login' telnetd auth required pam_unix.so try_first_pass Index: src/secure/Makefile.inc =================================================================== RCS file: /home/ncvs/src/secure/Makefile.inc,v retrieving revision 1.13.2.4 diff -u -u -r1.13.2.4 Makefile.inc --- src/secure/Makefile.inc 19 Apr 2002 11:58:35 -0000 1.13.2.4 +++ src/secure/Makefile.inc 30 Jun 2002 11:34:15 -0000 @@ -21,9 +21,4 @@ .if !defined(NO_OPENSSH) SSHDIR= ${.CURDIR}/../../../crypto/openssh -.if exists(${.OBJDIR}/../../lib/libssh) -LIBSSH= ${.OBJDIR}/../../lib/libssh/libssh.a -.else -LIBSSH= ${.CURDIR}/../../lib/libssh/libssh.a -.endif .endif Index: src/secure/lib/Makefile =================================================================== RCS file: /home/ncvs/src/secure/lib/Makefile,v retrieving revision 1.19.2.3 diff -u -u -r1.19.2.3 Makefile --- src/secure/lib/Makefile 18 Sep 2000 03:00:05 -0000 1.19.2.3 +++ src/secure/lib/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,14 +1,14 @@ # $FreeBSD: src/secure/lib/Makefile,v 1.19.2.3 2000/09/18 03:00:05 kris Exp $ SUBDIR= libcipher -.if !defined(NOCRYPT) && !defined(MAKE_KERBEROS4) +.if !defined(NOCRYPT) && !defined(MAKE_KERBEROS4) && !defined(MAKE_KERBEROS5) SUBDIR+=libtelnet .endif .if !defined(NO_OPENSSL) SUBDIR+=libcrypto libssl -.endif .if !defined(NO_OPENSSH) SUBDIR+=libssh +.endif .endif .include Index: src/secure/lib/libssh/Makefile =================================================================== RCS file: /home/ncvs/src/secure/lib/libssh/Makefile,v retrieving revision 1.2.2.4 diff -u -u -r1.2.2.4 Makefile --- src/secure/lib/libssh/Makefile 28 Sep 2001 01:33:51 -0000 1.2.2.4 +++ src/secure/lib/libssh/Makefile 30 Jun 2002 13:20:08 -0000 @@ -2,33 +2,26 @@ # LIB= ssh -SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \ - cipher.c compat.c compress.c crc32.c deattack.c \ +SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \ + cipher.c compat.c compress.c crc32.c deattack.c fatal.c \ hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \ - rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \ + rsa.c tildexpand.c ttymodes.c xmalloc.c atomicio.c \ key.c dispatch.c kex.c mac.c uuencode.c misc.c \ - cli.c rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \ - version.c - - -NOPIC= yes -INTERNALLIB= yes -INTERNALSTATICLIB= yes + rijndael.c ssh-dss.c ssh-rsa.c dh.c kexdh.c kexgex.c \ + scard.c monitor_wrap.c monitor_fdpass.c msg.c +# Portability layer +SRCS+= bsd-misc.c entropy.c +# FreeBSD additions +SRCS+= version.c +CFLAGS+=-I${SSHDIR} .if defined(COMPAT_GETADDRINFO) SRCS+= getaddrinfo.c getnameinfo.c name6.c rcmd.c bindresvport.c .endif -.if defined(MAKE_KERBEROS4) && \ - ((${MAKE_KERBEROS4} == "yes") || (${MAKE_KERBEROS4} == "YES")) -CFLAGS+= -DKRB4 -.endif # MAKE_KERBEROS4 - -.if defined(MAKE_KERBEROS5) && \ - ((${MAKE_KERBEROS5} == "yes") || (${MAKE_KERBEROS5} == "YES")) -CFLAGS+= -DKRB5 -.endif # MAKE_KERBEROS5 +DPADD= ${LIBCRYPTO} ${LIBZ} +LDADD+= -lcrypto -lz .include -.PATH: ${SSHDIR} ${SSHDIR}/lib +.PATH: ${SSHDIR} ${SSHDIR}/openbsd-compat Index: src/secure/libexec/Makefile =================================================================== RCS file: /home/ncvs/src/secure/libexec/Makefile,v retrieving revision 1.4.2.4 diff -u -u -r1.4.2.4 Makefile --- src/secure/libexec/Makefile 28 Oct 2000 23:05:13 -0000 1.4.2.4 +++ src/secure/libexec/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,6 +1,6 @@ # $FreeBSD: src/secure/libexec/Makefile,v 1.4.2.4 2000/10/28 23:05:13 kris Exp $ -.if !defined(NOCRYPT) && !defined(MAKE_KERBEROS4) && !defined(NO_OPENSSL) +.if !defined(NOCRYPT) && !defined(MAKE_KERBEROS4) && !defined(MAKE_KERBEROS5) && !defined(NO_OPENSSL) SUBDIR= telnetd .endif .if !defined(NO_OPENSSL) && !defined(NO_OPENSSH) Index: src/secure/libexec/sftp-server/Makefile =================================================================== RCS file: /home/ncvs/src/secure/libexec/sftp-server/Makefile,v retrieving revision 1.1.2.2 diff -u -u -r1.1.2.2 Makefile --- src/secure/libexec/sftp-server/Makefile 28 Sep 2001 01:33:51 -0000 1.1.2.2 +++ src/secure/libexec/sftp-server/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,12 +1,12 @@ # $FreeBSD: src/secure/libexec/sftp-server/Makefile,v 1.1.2.2 2001/09/28 01:33:51 green Exp $ -# PROG= sftp-server SRCS= sftp-server.c sftp-common.c MAN= sftp-server.8 +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto DPADD+= ${LIBSSH} ${LIBCRYPTO} +LDADD+= -lssh -lcrypto .include Index: src/secure/libexec/telnetd/Makefile =================================================================== RCS file: /home/ncvs/src/secure/libexec/telnetd/Makefile,v retrieving revision 1.19.2.2 diff -u -u -r1.19.2.2 Makefile --- src/secure/libexec/telnetd/Makefile 13 Apr 2002 11:00:49 -0000 1.19.2.2 +++ src/secure/libexec/telnetd/Makefile 30 Jun 2002 12:17:09 -0000 @@ -18,7 +18,7 @@ DPADD= ${LIBUTIL} ${LIBTERMCAP} ${LIBTELNET} ${LIBMP} ${LIBCRYPTO} \ ${LIBCRYPT} ${LIBPAM} -LDADD= -lutil -ltermcap ${LIBTELNET} -lmp -lcrypto \ +LDADD+= -lutil -ltermcap ${LIBTELNET} -lmp -lcrypto \ -lcrypt ${MINUSLPAM} .include Index: src/secure/usr.bin/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/Makefile,v retrieving revision 1.14.2.2 diff -u -u -r1.14.2.2 Makefile --- src/secure/usr.bin/Makefile 4 Mar 2002 10:18:10 -0000 1.14.2.2 +++ src/secure/usr.bin/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,13 +1,13 @@ # $FreeBSD: src/secure/usr.bin/Makefile,v 1.14.2.2 2002/03/04 10:18:10 ru Exp $ SUBDIR= bdes -.if !defined(NOCRYPT) && !defined(NO_OPENSSL) && !defined(MAKE_KERBEROS4) +.if !defined(NOCRYPT) && !defined(NO_OPENSSL) && !defined(MAKE_KERBEROS4) && !defined(MAKE_KERBEROS5) SUBDIR+=telnet .endif .if !defined(NO_OPENSSL) SUBDIR+=openssl .if !defined(NO_OPENSSH) -SUBDIR+=scp sftp ssh ssh-add ssh-agent ssh-keygen ssh-keyscan +SUBDIR+=scp sftp ssh ssh-add ssh-agent ssh-keygen ssh-keyscan ssh-keysign .endif .endif Index: src/secure/usr.bin/openssl/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/openssl/Makefile,v retrieving revision 1.11.2.3 diff -u -u -r1.11.2.3 Makefile --- src/secure/usr.bin/openssl/Makefile 4 Jul 2001 23:24:42 -0000 1.11.2.3 +++ src/secure/usr.bin/openssl/Makefile 30 Jun 2002 12:17:09 -0000 @@ -9,7 +9,7 @@ MAINTAINER= kris -LDADD= -lssl -lcrypto +LDADD+= -lssl -lcrypto MLINKS= openssl.1 ssl.8 CFLAGS+= -DMONOLITH -I${.CURDIR} Index: src/secure/usr.bin/scp/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/scp/Makefile,v retrieving revision 1.2.2.1 diff -u -u -r1.2.2.1 Makefile --- src/secure/usr.bin/scp/Makefile 28 Sep 2001 01:33:51 -0000 1.2.2.1 +++ src/secure/usr.bin/scp/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,11 +1,10 @@ # $FreeBSD: src/secure/usr.bin/scp/Makefile,v 1.2.2.1 2001/09/28 01:33:51 green Exp $ -# PROG= scp -SRCS= scp.c scp-common.c +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto -lutil -lz -DPADD+= ${LIBSSH} ${LIBCRYPTO} ${LIBUTIL} ${LIBZ} +DPADD= ${LIBSSH} +LDADD+= -lssh .include Index: src/secure/usr.bin/sftp/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/sftp/Makefile,v retrieving revision 1.1.2.1 diff -u -u -r1.1.2.1 Makefile --- src/secure/usr.bin/sftp/Makefile 8 Oct 2001 14:11:00 -0000 1.1.2.1 +++ src/secure/usr.bin/sftp/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,11 +1,11 @@ # $FreeBSD: src/secure/usr.bin/sftp/Makefile,v 1.1.2.1 2001/10/08 14:11:00 green Exp $ -# PROG= sftp -SRCS= sftp.c sftp-client.c sftp-int.c sftp-common.c sftp-glob.c scp-common.c +SRCS= sftp.c sftp-client.c sftp-int.c sftp-common.c sftp-glob.c +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto -DPADD+= ${LIBSSH} ${LIBCRYPTO} +DPADD= ${LIBSSH} ${LIBCRYPTO} +LDADD+= -lssh -lcrypto .include Index: src/secure/usr.bin/ssh/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/ssh/Makefile,v retrieving revision 1.4.2.5 diff -u -u -r1.4.2.5 Makefile --- src/secure/usr.bin/ssh/Makefile 28 Sep 2001 01:33:52 -0000 1.4.2.5 +++ src/secure/usr.bin/ssh/Makefile 30 Jun 2002 12:20:32 -0000 @@ -2,36 +2,36 @@ # PROG= ssh +CFLAGS+=-I${SSHDIR} .if defined(ENABLE_SUID_SSH) BINMODE=4555 .endif LINKS= ${BINDIR}/ssh ${BINDIR}/slogin +MAN= ssh.1 ssh_config.5 MLINKS= ssh.1 slogin.1 SRCS= ssh.c readconf.c clientloop.c sshtty.c \ sshconnect.c sshconnect1.c sshconnect2.c -.if defined(MAKE_KERBEROS4) && \ - ((${MAKE_KERBEROS4} == "yes") || (${MAKE_KERBEROS4} == "YES")) +.if defined(MAKE_KERBEROS4) DISTRIBUTION=krb4 CFLAGS+= -DKRB4 LDADD+= -lkrb -lcom_err DPADD+= ${LIBKRB} ${LIBCOM_ERR} -.endif # MAKE_KERBEROS4 +.endif -.if defined(MAKE_KERBEROS5) && \ - ((${MAKE_KERBEROS5} == "yes") || (${MAKE_KERBEROS5} == "YES")) +.if defined(MAKE_KERBEROS5) DISTRIBUTION=krb5 -CFLAGS+= -DKRB5 +CFLAGS+= -DKRB5 -DHEIMDAL LDADD+= -lkrb5 -lasn1 -lcom_err -lmd -L${.OBJDIR}/../../../kerberos5/lib/libroken -lroken -lcrypt DPADD+= ${LIBKRB5} ${LIBCOM_ERR} ${LIBASN1} ${LIBMD} ${LIBCRYPT} -.endif # MAKE_KERBEROS5 +.endif .if defined(X11BASE) CFLAGS+= -DXAUTH_PATH=\"${X11BASE}/bin/xauth\" .endif -LDADD+= ${LIBSSH} -lcrypto -lutil -lz +LDADD+= -lssh -lcrypto -lutil -lz DPADD+= ${LIBSSH} ${LIBCRYPTO} ${LIBUTIL} ${LIBZ} .include Index: src/secure/usr.bin/ssh-add/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/ssh-add/Makefile,v retrieving revision 1.2.2.1 diff -u -u -r1.2.2.1 Makefile --- src/secure/usr.bin/ssh-add/Makefile 28 Sep 2001 01:33:52 -0000 1.2.2.1 +++ src/secure/usr.bin/ssh-add/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,11 +1,10 @@ # $FreeBSD: src/secure/usr.bin/ssh-add/Makefile,v 1.2.2.1 2001/09/28 01:33:52 green Exp $ -# PROG= ssh-add -SRCS= ssh-add.c +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto -DPADD+= ${LIBSSH} ${LIBCRYPTO} +DPADD= ${LIBSSH} ${LIBCRYPTO} +LDADD+= -lssh -lcrypto .include Index: src/secure/usr.bin/ssh-agent/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/ssh-agent/Makefile,v retrieving revision 1.2.2.1 diff -u -u -r1.2.2.1 Makefile --- src/secure/usr.bin/ssh-agent/Makefile 28 Sep 2001 01:33:52 -0000 1.2.2.1 +++ src/secure/usr.bin/ssh-agent/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,11 +1,10 @@ # $FreeBSD: src/secure/usr.bin/ssh-agent/Makefile,v 1.2.2.1 2001/09/28 01:33:52 green Exp $ -# PROG= ssh-agent -SRCS= ssh-agent.c +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto -DPADD+= ${LIBSSH} ${LIBCRYPTO} +DPADD= ${LIBSSH} ${LIBCRYPTO} +LDADD+= -lssh -lcrypto .include Index: src/secure/usr.bin/ssh-keygen/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/ssh-keygen/Makefile,v retrieving revision 1.2.2.2 diff -u -u -r1.2.2.2 Makefile --- src/secure/usr.bin/ssh-keygen/Makefile 28 Sep 2001 01:33:53 -0000 1.2.2.2 +++ src/secure/usr.bin/ssh-keygen/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,11 +1,10 @@ # $FreeBSD: src/secure/usr.bin/ssh-keygen/Makefile,v 1.2.2.2 2001/09/28 01:33:53 green Exp $ -# PROG= ssh-keygen -SRCS= ssh-keygen.c +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto -DPADD+= ${LIBSSH} ${LIBCRYPTO} +DPADD= ${LIBSSH} ${LIBCRYPTO} +LDADD+= -lssh -lcrypto .include Index: src/secure/usr.bin/ssh-keyscan/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/ssh-keyscan/Makefile,v retrieving revision 1.1.2.1 diff -u -u -r1.1.2.1 Makefile --- src/secure/usr.bin/ssh-keyscan/Makefile 8 Oct 2001 19:25:24 -0000 1.1.2.1 +++ src/secure/usr.bin/ssh-keyscan/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,11 +1,10 @@ # $FreeBSD: src/secure/usr.bin/ssh-keyscan/Makefile,v 1.1.2.1 2001/10/08 19:25:24 green Exp $ -# PROG= ssh-keyscan -SRCS= ssh-keyscan.c +CFLAGS+=-I${SSHDIR} -LDADD+= ${LIBSSH} -lcrypto -DPADD+= ${LIBSSH} ${LIBCRYPTO} +DPADD= ${LIBSSH} ${LIBCRYPTO} ${LIBZ} +LDADD+= -lssh -lcrypto -lz .include Index: src/secure/usr.bin/ssh-keysign/Makefile =================================================================== RCS file: src/secure/usr.bin/ssh-keysign/Makefile diff -N src/secure/usr.bin/ssh-keysign/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/secure/usr.bin/ssh-keysign/Makefile 30 Jun 2002 12:17:09 -0000 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +PROG= ssh-keysign +MAN= ssh-keysign.8 +CFLAGS+=-I${SSHDIR} + +DPADD= ${LIBSSH} ${LIBCRYPTO} ${LIBZ} +LDADD+= -lssh -lcrypto -lz + +.include + +.PATH: ${SSHDIR} Index: src/secure/usr.bin/telnet/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.bin/telnet/Makefile,v retrieving revision 1.21.2.2 diff -u -u -r1.21.2.2 Makefile --- src/secure/usr.bin/telnet/Makefile 13 Apr 2002 11:00:50 -0000 1.21.2.2 +++ src/secure/usr.bin/telnet/Makefile 30 Jun 2002 12:17:09 -0000 @@ -13,7 +13,7 @@ DPADD= ${LIBTERMCAP} ${LIBTELNET} ${LIBMP} \ ${LIBCRYPTO} ${LIBCRYPT} ${LIBIPSEC} ${LIBPAM} -LDADD= -ltermcap ${LIBTELNET} -lmp \ +LDADD+= -ltermcap ${LIBTELNET} -lmp \ -lcrypto -lcrypt -lipsec ${MINUSLPAM} .include Index: src/secure/usr.sbin/sshd/Makefile =================================================================== RCS file: /home/ncvs/src/secure/usr.sbin/sshd/Makefile,v retrieving revision 1.5.2.7 diff -u -u -r1.5.2.7 Makefile --- src/secure/usr.sbin/sshd/Makefile 28 Sep 2001 01:33:53 -0000 1.5.2.7 +++ src/secure/usr.sbin/sshd/Makefile 30 Jun 2002 12:17:09 -0000 @@ -1,36 +1,36 @@ # $FreeBSD: src/secure/usr.sbin/sshd/Makefile,v 1.5.2.7 2001/09/28 01:33:53 green Exp $ # -LOGINSRC= ${.CURDIR}/../../../usr.bin/login - PROG= sshd SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \ - sshpty.c sshlogin.c servconf.c serverloop.c \ + sshpty.c sshlogin.c servconf.c serverloop.c uidswap.c \ auth.c auth1.c auth2.c auth-options.c session.c \ - auth-chall.c auth2-chall.c auth-pam.c login_access.c groupaccess.c -MAN= sshd.8 - -CFLAGS+= -DLIBWRAP -DHAVE_LOGIN_CAP -DLOGIN_ACCESS -I${LOGINSRC} -DUSE_PAM -DHAVE_PAM_GETENVLIST + auth-chall.c auth2-chall.c groupaccess.c \ + auth-skey.c auth-bsdauth.c monitor_mm.c monitor.c \ + auth2-none.c auth2-passwd.c auth2-pubkey.c \ + auth2-hostbased.c auth2-kbdint.c \ + auth-pam.c auth2-pam.c auth2-pam-freebsd.c +# Portability layer +SRCS+= loginrec.c +MAN= sshd.8 sshd_config.5 +CFLAGS+=-I${SSHDIR} -.if defined(MAKE_KERBEROS4) && \ - ((${MAKE_KERBEROS4} == "yes") || (${MAKE_KERBEROS4} == "YES")) +.if defined(MAKE_KERBEROS4) DISTRIBUTION=krb4 CFLAGS+= -DKRB4 SRCS+= auth-krb4.c LDADD+= -lkrb -lcom_err DPADD+= ${LIBKRB} ${LIBCOM_ERR} -.endif # MAKE_KERBEROS4 +.endif -.if defined(MAKE_KERBEROS5) && \ - ((${MAKE_KERBEROS5} == "yes") || (${MAKE_KERBEROS5} == "YES")) +.if defined(MAKE_KERBEROS5) DISTRIBUTION=krb5 -CFLAGS+= -DKRB5 +CFLAGS+= -DKRB5 -DHEIMDAL SRCS+= auth-krb5.c LDADD+= -lkrb5 -lasn1 -lcom_err -lmd -L${.OBJDIR}/../../../kerberos5/lib/libroken -lroken DPADD+= ${LIBKRB5} ${LIBCOM_ERR} ${LIBASN1} ${LIBMD} -.endif # MAKE_KERBEROS5 +.endif -CFLAGS+= -DSKEY LDADD+= -lopie -lmd DPADD+= ${LIBOPIE} ${LIBMD} @@ -38,9 +38,9 @@ CFLAGS+= -DXAUTH_PATH=\"${X11BASE}/bin/xauth\" .endif -LDADD+= ${LIBSSH} -lcrypt -lcrypto -lutil -lz -lwrap ${MINUSLPAM} +LDADD+= -lssh -lcrypt -lcrypto -lutil -lz -lwrap ${MINUSLPAM} DPADD+= ${LIBSSH} ${LIBCRYPT} ${LIBCRYPTO} ${LIBUTIL} ${LIBZ} ${LIBWRAP} ${LIBPAM} .include -.PATH: ${SSHDIR} ${LOGINSRC} +.PATH: ${SSHDIR}