From e9a17296ccbb7bb4f9a0affffe58d2240768a7d4 Mon Sep 17 00:00:00 2001 From: jbasney Date: Wed, 13 Mar 2002 14:49:38 +0000 Subject: [PATCH] Import of OpenSSH 3.1p1 --- openssh/.cvsignore | 2 + openssh/CREDITS | 3 +- openssh/ChangeLog | 907 +++++++++++++++++++++- openssh/INSTALL | 12 - openssh/LICENCE | 40 +- openssh/Makefile.in | 37 +- openssh/README | 2 +- openssh/TODO | 4 + openssh/acconfig.h | 12 +- openssh/auth-bsdauth.c | 102 +-- openssh/auth-krb4.c | 74 +- openssh/auth-krb5.c | 107 +-- openssh/auth-options.c | 4 +- openssh/auth-options.h | 4 +- openssh/auth-pam.c | 2 +- openssh/auth-passwd.c | 7 +- openssh/auth-rh-rsa.c | 23 +- openssh/auth-rhosts.c | 25 +- openssh/auth-rsa.c | 49 +- openssh/auth-sia.c | 4 +- openssh/auth-skey.c | 11 +- openssh/auth.c | 45 +- openssh/auth.h | 23 +- openssh/auth1.c | 80 +- openssh/auth2-chall.c | 67 +- openssh/auth2-pam.c | 6 +- openssh/auth2.c | 236 +++--- openssh/authfd.c | 14 +- openssh/authfd.h | 8 +- openssh/authfile.c | 69 +- openssh/authfile.h | 4 +- openssh/bufaux.c | 25 +- openssh/bufaux.h | 15 +- openssh/buffer.c | 27 +- openssh/buffer.h | 14 +- openssh/canohost.c | 36 +- openssh/channels.c | 521 +++++-------- openssh/channels.h | 102 ++- openssh/cipher.c | 708 ++++++++--------- openssh/cipher.h | 65 +- openssh/clientloop.c | 75 +- openssh/compat.c | 138 ++-- openssh/compat.h | 3 +- openssh/compress.c | 26 +- openssh/compress.h | 4 +- openssh/config.guess | 438 +++++------ openssh/configure.ac | 502 +++++++----- openssh/contrib/README | 7 +- openssh/contrib/aix/README | 36 + openssh/contrib/aix/buildbff.sh | 187 +++++ openssh/contrib/aix/inventory.sh | 61 ++ openssh/contrib/caldera/openssh.spec | 2 +- openssh/contrib/cygwin/README | 18 +- openssh/contrib/gnome-ssh-askpass.c | 36 +- openssh/contrib/redhat/openssh.spec | 2 +- openssh/contrib/suse/openssh.spec | 2 +- openssh/crc32.h | 4 +- openssh/deattack.c | 13 +- openssh/defines.h | 33 +- openssh/dh.c | 35 +- openssh/dispatch.c | 38 +- openssh/dispatch.h | 8 +- openssh/entropy.c | 933 ++-------------------- openssh/fatal.c | 40 + openssh/getput.h | 4 +- openssh/groupaccess.c | 3 +- openssh/hostfile.c | 15 +- openssh/hostfile.h | 4 +- openssh/includes.h | 2 +- openssh/kex.c | 51 +- openssh/kex.h | 6 +- openssh/kexdh.c | 39 +- openssh/kexgex.c | 56 +- openssh/key.c | 113 +-- openssh/key.h | 6 +- openssh/log.c | 27 +- openssh/log.h | 10 +- openssh/loginrec.c | 8 +- openssh/mac.c | 6 +- openssh/match.c | 36 +- openssh/match.h | 7 +- openssh/misc.c | 40 +- openssh/misc.h | 3 +- openssh/mpaux.h | 4 +- openssh/myproposal.h | 6 +- openssh/nchan.c | 259 +++---- openssh/openbsd-compat/Makefile.in | 7 +- openssh/openbsd-compat/base64.h | 2 +- openssh/openbsd-compat/bsd-cygwin_util.c | 28 +- openssh/openbsd-compat/bsd-cygwin_util.h | 3 +- openssh/openbsd-compat/daemon.c | 3 + openssh/openbsd-compat/dirname.c | 6 +- openssh/openbsd-compat/fake-queue.h | 15 +- openssh/openbsd-compat/mktemp.c | 5 +- openssh/openbsd-compat/openbsd-compat.h | 2 + openssh/openbsd-compat/port-aix.c | 126 +++ openssh/openbsd-compat/port-aix.h | 10 + openssh/openbsd-compat/port-irix.c | 61 ++ openssh/openbsd-compat/port-irix.h | 5 + openssh/openbsd-compat/readpassphrase.c | 135 ++-- openssh/openbsd-compat/realpath.c | 8 +- openssh/openbsd-compat/setenv.c | 5 +- openssh/openbsd-compat/setproctitle.c | 2 +- openssh/packet.c | 225 +++--- openssh/packet.h | 37 +- openssh/pathnames.h | 43 +- openssh/radix.c | 20 +- openssh/readconf.c | 44 +- openssh/readconf.h | 6 +- openssh/readpass.c | 54 +- openssh/rijndael.c | 351 +++++---- openssh/rijndael.h | 6 +- openssh/rsa.c | 11 +- openssh/rsa.h | 4 +- openssh/scard.c | 19 +- openssh/scard.h | 4 +- openssh/scard/.cvsignore | 2 + openssh/scp.1 | 5 +- openssh/scp.c | 9 +- openssh/servconf.c | 938 ++++++++++++----------- openssh/servconf.h | 15 +- openssh/serverloop.c | 166 ++-- openssh/session.c | 902 +++++++++------------- openssh/session.h | 4 +- openssh/sftp-client.c | 599 ++++++++++----- openssh/sftp-client.h | 49 +- openssh/sftp-common.c | 4 +- openssh/sftp-glob.c | 41 +- openssh/sftp-glob.h | 14 +- openssh/sftp-int.c | 122 ++- openssh/sftp-int.h | 4 +- openssh/sftp-server.c | 24 +- openssh/sftp.1 | 55 +- openssh/sftp.c | 114 +-- openssh/sftp.h | 3 +- openssh/ssh-add.1 | 27 +- openssh/ssh-add.c | 82 +- openssh/ssh-agent.1 | 24 +- openssh/ssh-agent.c | 215 +++--- openssh/ssh-dss.c | 43 +- openssh/ssh-dss.h | 6 +- openssh/ssh-keygen.1 | 21 +- openssh/ssh-keygen.c | 70 +- openssh/ssh-keyscan.1 | 8 +- openssh/ssh-keyscan.c | 48 +- openssh/ssh-rand-helper.c | 809 +++++++++++++++++++ openssh/ssh-rsa.c | 30 +- openssh/ssh-rsa.h | 6 +- openssh/ssh.1 | 69 +- openssh/ssh.c | 85 +- openssh/ssh.h | 4 +- openssh/ssh2.h | 18 +- openssh/ssh_config | 18 +- openssh/sshconnect.c | 119 ++- openssh/sshconnect1.c | 362 +++++---- openssh/sshconnect2.c | 124 +-- openssh/sshd.8 | 153 ++-- openssh/sshd.c | 163 ++-- openssh/sshd_config | 104 +-- openssh/sshlogin.c | 8 +- openssh/sshlogin.h | 7 +- openssh/sshpty.c | 22 +- openssh/sshpty.h | 4 +- openssh/sshtty.c | 4 +- openssh/ttymodes.c | 5 +- openssh/ttymodes.h | 3 +- openssh/uidswap.c | 6 +- openssh/uuencode.c | 9 +- openssh/uuencode.h | 4 +- openssh/version.h | 5 +- openssh/xmalloc.h | 4 +- 171 files changed, 7813 insertions(+), 6035 deletions(-) create mode 100644 openssh/contrib/aix/README create mode 100755 openssh/contrib/aix/buildbff.sh create mode 100755 openssh/contrib/aix/inventory.sh create mode 100644 openssh/fatal.c create mode 100644 openssh/openbsd-compat/port-aix.c create mode 100644 openssh/openbsd-compat/port-aix.h create mode 100644 openssh/openbsd-compat/port-irix.c create mode 100644 openssh/openbsd-compat/port-irix.h create mode 100644 openssh/scard/.cvsignore create mode 100644 openssh/ssh-rand-helper.c diff --git a/openssh/.cvsignore b/openssh/.cvsignore index a473d1f..549c5e4 100644 --- a/openssh/.cvsignore +++ b/openssh/.cvsignore @@ -19,3 +19,5 @@ ssh_prng_cmds *.out *.0 buildit.sh +autom4te.cache +ssh-rand-helper diff --git a/openssh/CREDITS b/openssh/CREDITS index c591e5c..bcc0359 100644 --- a/openssh/CREDITS +++ b/openssh/CREDITS @@ -26,6 +26,7 @@ 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 @@ -35,7 +36,7 @@ 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 +HARUYAMA Seigo - Translations & doc fixes Hideaki YOSHIFUJI - IPv6 and bug fixes Hiroshi Takekawa - Configure fixes Holger Trapp - KRB4/AFS config patch diff --git a/openssh/ChangeLog b/openssh/ChangeLog index d79e7fb..bd2d9c5 100644 --- a/openssh/ChangeLog +++ b/openssh/ChangeLog @@ -1,9 +1,904 @@ -20011202 - - (djm) Syn with OpenBSD OpenSSH-3.0.2 - - markus@cvs.openbsd.org - [session.c sshd.8 version.h] - Don't allow authorized_keys specified environment variables when - UseLogin in active +20020307 + - (djm) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/03/06 00:20:54 + [compat.c dh.c] + compat.c + - markus@cvs.openbsd.org 2002/03/06 00:23:27 + [compat.c dh.c] + undo + - markus@cvs.openbsd.org 2002/03/06 00:24:39 + [compat.c] + compat.c + - markus@cvs.openbsd.org 2002/03/06 00:25:55 + [version.h] + OpenSSH_3.1 + - (djm) Update RPM spec files with new version number + +20020305 + - stevesk@cvs.openbsd.org 2002/03/02 09:34:42 + [LICENCE] + correct copyright dates for scp license; ok markus@ + +20020304 + - OpenBSD CVS Sync + - deraadt@cvs.openbsd.org 2002/02/26 18:52:32 + [sftp.1] + Ic cannot have that many arguments; spotted by mouring@etoh.eviladmin.org + - mouring@cvs.openbsd.org 2002/02/26 19:04:37 + [sftp.1] + > Ic cannot have that many arguments; spotted by mouring@etoh.eviladmin.org + Last Ic on the first line should not have a space between it and the final + comma. + - deraadt@cvs.openbsd.org 2002/02/26 19:06:43 + [sftp.1] + no, look closely. the comma was highlighted. split .Ic even more + - stevesk@cvs.openbsd.org 2002/02/26 20:03:51 + [misc.c] + use socklen_t + - stevesk@cvs.openbsd.org 2002/02/27 21:23:13 + [canohost.c channels.c packet.c sshd.c] + remove unneeded casts in [gs]etsockopt(); ok markus@ + - markus@cvs.openbsd.org 2002/02/28 15:46:33 + [authfile.c kex.c kexdh.c kexgex.c key.c ssh-dss.c] + add some const EVP_MD for openssl-0.9.7 + - stevesk@cvs.openbsd.org 2002/02/28 19:36:28 + [auth.c match.c match.h] + delay hostname lookup until we see a ``@'' in DenyUsers and AllowUsers + for sshd -u0; ok markus@ + - stevesk@cvs.openbsd.org 2002/02/28 20:36:42 + [sshd.8] + DenyUsers allows user@host pattern also + - stevesk@cvs.openbsd.org 2002/02/28 20:46:10 + [sshd.8] + -u0 DNS for user@host + - stevesk@cvs.openbsd.org 2002/02/28 20:56:00 + [auth.c] + log user not allowed details, from dwd@bell-labs.com; ok markus@ + - markus@cvs.openbsd.org 2002/03/01 13:12:10 + [auth.c match.c match.h] + undo the 'delay hostname lookup' change + match.c must not use compress.c (via canonhost.c/packet.c) + thanks to wilfried@ + - markus@cvs.openbsd.org 2002/03/04 12:43:06 + [auth-passwd.c auth-rh-rsa.c auth-rhosts.c] + - markus@cvs.openbsd.org 2002/03/04 13:10:46 + [misc.c] + error-> debug, because O_NONBLOCK for /dev/null causes too many different + errnos; ok stevesk@, deraadt@ + unused include + - stevesk@cvs.openbsd.org 2002/03/04 17:27:39 + [auth-krb5.c auth-options.h auth.h authfd.h authfile.h bufaux.h buffer.h + channels.h cipher.h compat.h compress.h crc32.h deattack.c getput.h + groupaccess.c misc.c mpaux.h packet.h readconf.h rsa.h scard.h + servconf.h ssh-agent.c ssh.h ssh2.h sshpty.h sshtty.c ttymodes.h + uuencode.c xmalloc.h] + $OpenBSD$ and RCSID() cleanup: don't use RCSID() in .h files; add + missing RCSID() to .c files and remove dup /*$OpenBSD$*/ from .c + files. ok markus@ + - stevesk@cvs.openbsd.org 2002/03/04 18:30:23 + [ssh-keyscan.c] + handle connection close during read of protocol version string. + fixes erroneous "bad greeting". ok markus@ + - markus@cvs.openbsd.org 2002/03/04 19:37:58 + [channels.c] + off by one; thanks to joost@pine.nl + - (bal) Added contrib/aix/ to support BFF package generation provided + by Darren Tucker +20020226 + - (tim) Bug 12 [configure.ac] add sys/bitypes.h to int64_t tests + based on patch by mooney@dogbert.cc.ndsu.nodak.edu (Tim Mooney) + Bug 45 [configure.ac] modify skey test to work around conflict with autoconf + reported by nolan@naic.edu (Michael Nolan) + patch by Pekka Savola + Bug 74 [configure.ac defines.h] add sig_atomic_t test + reported by dwd@bell-labs.com (Dave Dykstra) + Bug 102 [defines.h] UNICOS fixes. patch by wendyp@cray.com + [configure.ac Makefile.in] link libwrap only with sshd + based on patch by Maciej W. Rozycki + Bug 123 link libpam only with sshd + reported by peak@argo.troja.mff.cuni.cz (Pavel Kankovsky) + [configure.ac defines.h] modify previous SCO3 fix to not break Solaris 7 + [acconfig.h] remove unused HAVE_REGCOMP + [configure.ac] put back in search for prngd-socket + - (stevesk) openbsd-compat/base64.h: typo in comment + - (bal) Update sshd_config CVSID + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/02/15 23:54:10 + [auth-krb5.c] + krb5_get_err_text() does not like context==NULL; he@nordu.net via google; + ok provos@ + - markus@cvs.openbsd.org 2002/02/22 12:20:34 + [log.c log.h ssh-keyscan.c] + overwrite fatal() in ssh-keyscan.c; fixes pr 2354; ok provos@ + - markus@cvs.openbsd.org 2002/02/23 17:59:02 + [kex.c kexdh.c kexgex.c] + don't allow garbage after payload. + - stevesk@cvs.openbsd.org 2002/02/24 16:09:52 + [sshd.c] + use u_char* here; ok markus@ + - markus@cvs.openbsd.org 2002/02/24 16:57:19 + [sftp-client.c] + early close(), missing free; ok stevesk@ + - markus@cvs.openbsd.org 2002/02/24 16:58:32 + [packet.c] + make 'cp' unsigned and merge with 'ucp'; ok stevesk@ + - markus@cvs.openbsd.org 2002/02/24 18:31:09 + [uuencode.c] + typo in comment + - markus@cvs.openbsd.org 2002/02/24 19:14:59 + [auth2.c authfd.c authfd.h authfile.c kexdh.c kexgex.c key.c key.h + ssh-dss.c ssh-dss.h ssh-keygen.c ssh-rsa.c ssh-rsa.h sshconnect2.c] + signed vs. unsigned: make size arguments u_int, ok stevesk@ + - stevesk@cvs.openbsd.org 2002/02/24 19:59:42 + [channels.c misc.c] + disable Nagle in connect_to() and channel_post_port_listener() (port + forwarding endpoints). the intention is to preserve the on-the-wire + appearance to applications at either end; the applications can then + enable TCP_NODELAY according to their requirements. ok markus@ + - markus@cvs.openbsd.org 2002/02/25 16:33:27 + [ssh-keygen.c sshconnect2.c uuencode.c uuencode.h] + more u_* fixes + - (bal) Imported missing fatal.c and fixed up Makefile.in + - (tim) [configure.ac] correction to Bug 123 fix + [configure.ac] correction to sig_atomic_t test + +20020225 + - (bal) Last AIX patch. Moved aix_usrinfo() outside of do_setuserconext() + since we need more session information than provided by that function. + +20020224 + - (bal) Drop Session *s usage in ports-aix.[ch] and pass just what we + need to do the jobs (AIX still does not fully compile, but that is + coming). + - (bal) Part two.. Drop unused AIX header, fix up missing char *cp. All + that is left is handling aix_usrinfo(). + - (tim) [loginrec.c session.c sshlogin.c sshlogin.h] Bug 84 + patch by wknox@mitre.org (William Knox). + [sshlogin.h] declare record_utmp_only for session.c + +20020221 + - (bal) Minor session.c fixup for cygwin. mispelt 'is_winnt' variable. + +20020219 + - (djm) OpenBSD CVS Sync + - mpech@cvs.openbsd.org 2002/02/13 08:33:47 + [ssh-keyscan.1] + When you give command examples and etc., in a manual page prefix them with: $ command + or + # command + - markus@cvs.openbsd.org 2002/02/14 23:27:59 + [channels.c] + increase the SSH v2 window size to 4 packets. comsumes a little + bit more memory for slow receivers but increases througput. + - markus@cvs.openbsd.org 2002/02/14 23:28:00 + [channels.h session.c ssh.c] + increase the SSH v2 window size to 4 packets. comsumes a little + bit more memory for slow receivers but increases througput. + - markus@cvs.openbsd.org 2002/02/14 23:41:01 + [authfile.c cipher.c cipher.h kex.c kex.h packet.c] + hide some more implementation details of cipher.[ch] and prepares for move + to EVP, ok deraadt@ + - stevesk@cvs.openbsd.org 2002/02/16 14:53:37 + [ssh-keygen.1] + -t required now for key generation + - stevesk@cvs.openbsd.org 2002/02/16 20:40:08 + [ssh-keygen.c] + default to rsa keyfile path for non key generation operations where + keyfile not specified. fixes core dump in those cases. ok markus@ + - millert@cvs.openbsd.org 2002/02/16 21:27:53 + [auth.h] + Part one of userland __P removal. Done with a simple regexp with + some minor hand editing to make comments line up correctly. Another + pass is forthcoming that handles the cases that could not be done + automatically. + - millert@cvs.openbsd.org 2002/02/17 19:42:32 + [auth.h] + Manual cleanup of remaining userland __P use (excluding packages + maintained outside the tree) + - markus@cvs.openbsd.org 2002/02/18 13:05:32 + [cipher.c cipher.h] + switch to EVP, ok djm@ deraadt@ + - markus@cvs.openbsd.org 2002/02/18 17:55:20 + [ssh.1] + -q: Fatal errors are _not_ displayed. + - deraadt@cvs.openbsd.org 2002/02/19 02:50:59 + [sshd_config] + stategy is not an english word + - (bal) Migrated IRIX jobs/projects/audit/etc code to + openbsd-compat/port-irix.[ch] to improve readiblity of do_child() + - (bal) Migrated AIX getuserattr and usrinfo code to + openbsd-compat/port-aix.[c] to improve readilbity of do_child() and + simplify our diffs against upstream source. + - (bal) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/02/15 23:11:26 + [session.c] + split do_child(), ok mouring@ + - markus@cvs.openbsd.org 2002/02/16 00:51:44 + [session.c] + typo + - (bal) CVS ID sync since the last two patches were merged mistakenly + +20020218 + - (tim) newer config.guess from ftp://ftp.gnu.org/gnu/config/config.guess + +20020213 + - (djm) Don't use system sys/queue.h on AIX. Report from + gert@greenie.muc.de + - (djm) Bug #114 - not starting PAM for SSH protocol 1 invalid users + +20020213 + - (djm) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/02/11 16:10:15 + [kex.c] + restore kexinit handler if we reset the dispatcher, this unbreaks + rekeying s/kex_clear_dispatch/kex_reset_dispatch/ + - markus@cvs.openbsd.org 2002/02/11 16:15:46 + [sshconnect1.c] + include md5.h, not evp.h + - markus@cvs.openbsd.org 2002/02/11 16:17:55 + [sshd.c] + do not complain about port > 1024 if rhosts-auth is disabled + - markus@cvs.openbsd.org 2002/02/11 16:19:39 + [sshd.c] + include md5.h not hmac.h + - markus@cvs.openbsd.org 2002/02/11 16:21:42 + [match.c] + support up to 40 algorithms per proposal + - djm@cvs.openbsd.org 2002/02/12 12:32:27 + [sftp.1 sftp.c sftp-client.c sftp-client.h sftp-int.c] + Perform multiple overlapping read/write requests in file transfer. Mostly + done by Tobias Ringstrom ; ok markus@ + - djm@cvs.openbsd.org 2002/02/12 12:44:46 + [sftp-client.c] + Let overlapped upload path handle servers which reorder ACKs. This may be + permitted by the protocol spec; ok markus@ + - markus@cvs.openbsd.org 2002/02/13 00:28:13 + [sftp-server.c] + handle SSH2_FILEXFER_ATTR_SIZE in SSH2_FXP_(F)SETSTAT; ok djm@ + - markus@cvs.openbsd.org 2002/02/13 00:39:15 + [readpass.c] + readpass.c is not longer from UCB, since we now use readpassphrase(3) + - djm@cvs.openbsd.org 2002/02/13 00:59:23 + [sftp-client.c sftp-client.h sftp-glob.c sftp-glob.h sftp.h] + [sftp-int.c sftp-int.h] + API cleanup and backwards compat for filexfer v.0 servers; ok markus@ + - (djm) Sync openbsd-compat with OpenBSD CVS too + - (djm) Bug #106: Add --without-rpath configure option. Patch from + Nicolas.Williams@ubsw.com + - (tim) [configure.ac, defines.h ] add rpc/rpc.h for INADDR_LOOPBACK + on SCO OSR3 + +20020210 + - (djm) OpenBSD CVS Sync + - deraadt@cvs.openbsd.org 2002/02/09 17:37:34 + [pathnames.h session.c ssh.1 sshd.8 sshd_config ssh-keyscan.1] + move ssh config files to /etc/ssh + - (djm) Adjust portable Makefile.in tnd ssh-rand-helper.c o match + - deraadt@cvs.openbsd.org 2002/02/10 01:07:05 + [readconf.h sshd.8] + more /etc/ssh; openbsd@davidkrause.com + +20020208 + - (djm) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2002/02/04 12:15:25 + [sshd.c] + add SYSLOG_FACILITY_NOT_SET = -1, SYSLOG_LEVEL_NOT_SET = -1, + fixes arm/netbsd; based on patch from bjh21@netbsd.org; ok djm@ + - stevesk@cvs.openbsd.org 2002/02/04 20:41:16 + [ssh-agent.1] + more sync for default ssh-add identities; ok markus@ + - djm@cvs.openbsd.org 2002/02/05 00:00:46 + [sftp.1 sftp.c sftp-client.c sftp-client.h sftp-int.c] + Add "-B" option to specify copy buffer length (default 32k); ok markus@ + - markus@cvs.openbsd.org 2002/02/05 14:32:55 + [channels.c channels.h ssh.c] + merge channel_request() into channel_request_start() + - markus@cvs.openbsd.org 2002/02/06 14:22:42 + [sftp.1] + sort options; ok mpech@, stevesk@ + - mpech@cvs.openbsd.org 2002/02/06 14:27:23 + [sftp.c] + sync usage() with manual. + - markus@cvs.openbsd.org 2002/02/06 14:37:22 + [session.c] + minor KNF + - markus@cvs.openbsd.org 2002/02/06 14:55:16 + [channels.c clientloop.c serverloop.c ssh.c] + channel_new never returns NULL, mouring@; ok djm@ + - markus@cvs.openbsd.org 2002/02/07 09:35:39 + [ssh.c] + remove bogus comments + +20020205 + - (djm) Cleanup after sync: + - :%s/reverse_mapping_check/verify_reverse_mapping/g + - (djm) OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2002/01/24 21:09:25 + [channels.c misc.c misc.h packet.c] + add set_nodelay() to set TCP_NODELAY on a socket (prep for nagle tuning). + no nagle changes just yet; ok djm@ markus@ + - stevesk@cvs.openbsd.org 2002/01/24 21:13:23 + [packet.c] + need misc.h for set_nodelay() + - markus@cvs.openbsd.org 2002/01/25 21:00:24 + [sshconnect2.c] + unused include + - markus@cvs.openbsd.org 2002/01/25 21:42:11 + [ssh-dss.c ssh-rsa.c] + use static EVP_MAX_MD_SIZE buffers for EVP_DigestFinal; ok stevesk@ + don't use evp_md->md_size, it's not public. + - markus@cvs.openbsd.org 2002/01/25 22:07:40 + [kex.c kexdh.c kexgex.c key.c mac.c] + use EVP_MD_size(evp_md) and not evp_md->md_size; ok steveks@ + - stevesk@cvs.openbsd.org 2002/01/26 16:44:22 + [includes.h session.c] + revert code to add x11 localhost display authorization entry for + hostname/unix:d and uts.nodename/unix:d if nodename was different than + hostname. just add entry for unix:d instead. ok markus@ + - stevesk@cvs.openbsd.org 2002/01/27 14:57:46 + [channels.c servconf.c servconf.h session.c sshd.8 sshd_config] + add X11UseLocalhost; ok markus@ + - stevesk@cvs.openbsd.org 2002/01/27 18:08:17 + [ssh.c] + handle simple case to identify FamilyLocal display; ok markus@ + - markus@cvs.openbsd.org 2002/01/29 14:27:57 + [ssh-add.c] + exit 2 if no agent, exit 1 if list fails; debian#61078; ok djm@ + - markus@cvs.openbsd.org 2002/01/29 14:32:03 + [auth2.c auth.c auth-options.c auth-rhosts.c auth-rh-rsa.c canohost.c] + [servconf.c servconf.h session.c sshd.8 sshd_config] + s/ReverseMappingCheck/VerifyReverseMapping/ and avoid confusion; + ok stevesk@ + - stevesk@cvs.openbsd.org 2002/01/29 16:29:02 + [session.c] + limit subsystem length in log; ok markus@ + - markus@cvs.openbsd.org 2002/01/29 16:41:19 + [ssh-add.1] + add DIAGNOSTICS; ok stevesk@ + - markus@cvs.openbsd.org 2002/01/29 22:46:41 + [session.c] + don't depend on servconf.c; ok djm@ + - markus@cvs.openbsd.org 2002/01/29 23:50:37 + [scp.1 ssh.1] + mention exit status; ok stevesk@ + - markus@cvs.openbsd.org 2002/01/31 13:35:11 + [kexdh.c kexgex.c] + cross check announced key type and type from key blob + - markus@cvs.openbsd.org 2002/01/31 15:00:05 + [serverloop.c] + no need for WNOHANG; ok stevesk@ + - markus@cvs.openbsd.org 2002/02/03 17:53:25 + [auth1.c serverloop.c session.c session.h] + don't use channel_input_channel_request and callback + use new server_input_channel_req() instead: + server_input_channel_req does generic request parsing on server side + session_input_channel_req handles just session specific things now + ok djm@ + - markus@cvs.openbsd.org 2002/02/03 17:55:55 + [channels.c channels.h] + remove unused channel_input_channel_request + - markus@cvs.openbsd.org 2002/02/03 17:58:21 + [channels.c channels.h ssh.c] + generic callbacks are not really used, remove and + add a callback for msg of type SSH2_MSG_CHANNEL_OPEN_CONFIRMATION + ok djm@ + - markus@cvs.openbsd.org 2002/02/03 17:59:23 + [sshconnect2.c] + more cross checking if announced vs. used key type; ok stevesk@ + - stevesk@cvs.openbsd.org 2002/02/03 22:35:57 + [ssh.1 sshd.8] + some KeepAlive cleanup/clarify; ok markus@ + - stevesk@cvs.openbsd.org 2002/02/03 23:22:59 + [ssh-agent.1] + ssh-add also adds $HOME/.ssh/id_rsa and $HOME/.ssh/id_dsa now. + - stevesk@cvs.openbsd.org 2002/02/04 00:53:39 + [ssh-agent.c] + unneeded includes + - markus@cvs.openbsd.org 2002/02/04 11:58:10 + [auth2.c] + cross checking of announced vs actual pktype in pubkey/hostbaed auth; + ok stevesk@ + - markus@cvs.openbsd.org 2002/02/04 12:15:25 + [log.c log.h readconf.c servconf.c] + add SYSLOG_FACILITY_NOT_SET = -1, SYSLOG_LEVEL_NOT_SET = -1, + fixes arm/netbsd; based on patch from bjh21@netbsd.org; ok djm@ + - stevesk@cvs.openbsd.org 2002/02/04 20:41:16 + [ssh-add.1] + more sync for default ssh-add identities; ok markus@ + - djm@cvs.openbsd.org 2002/02/04 21:53:12 + [sftp.1 sftp.c] + Add "-P" option to directly connect to a local sftp-server. Should be + useful for regression testing; ok markus@ + - djm@cvs.openbsd.org 2002/02/05 00:00:46 + [sftp.1 sftp.c sftp-client.c sftp-client.h sftp-int.c] + Add "-B" option to specify copy buffer length (default 32k); ok markus@ + +20020130 + - (djm) Delay PRNG seeding until we need it in ssh-keygen, from markus@ + - (tim) [configure.ac] fix logic on when ssh-rand-helper is installed. + [sshd_config] put back in line that tells what PATH was compiled into sshd. + +20020125 + - (djm) Don't grab Xserver or pointer by default. x11-ssh-askpass doesn't + and grabbing can cause deadlocks with kinput2. + +20020124 + - (stevesk) Makefile.in: bug #61; delete commented line for now. + +20020123 + - (djm) Fix non-standard shell syntax in autoconf. Patch from + Dave Dykstra + - (stevesk) fix --with-zlib= + - (djm) Use case statements in autoconf to clean up some tests + - (bal) reverted out of 5/2001 change to atexit(). I assume I + did it to handle SonyOS. If that is the case than we will + do a special case for them. + +20020122 + - (djm) autoconf hacking: + - We don't support --without-zlib currently, so don't allow it. + - Rework cryptographic random number support detection. We now detect + whether OpenSSL seeds itself. If it does, then we don't bother with + the ssh-rand-helper program. You can force the use of ssh-rand-helper + using the --with-rand-helper configure argument + - Simplify and clean up ssh-rand-helper configuration + - Add OpenSSL sanity check: verify that header version matches version + reported by library + - (djm) Fix some bugs I introduced into ssh-rand-helper yesterday + - OpenBSD CVS Sync + - djm@cvs.openbsd.org 2001/12/21 08:52:22 + [ssh-keygen.1 ssh-keygen.c] + Remove default (rsa1) key type; ok markus@ + - djm@cvs.openbsd.org 2001/12/21 08:53:45 + [readpass.c] + Avoid interruptable passphrase read; ok markus@ + - djm@cvs.openbsd.org 2001/12/21 10:06:43 + [ssh-add.1 ssh-add.c] + Try all standard key files (id_rsa, id_dsa, identity) when invoked with + no arguments; ok markus@ + - markus@cvs.openbsd.org 2001/12/21 12:17:33 + [serverloop.c] + remove ifdef for USE_PIPES since fdin != fdout; ok djm@ + - deraadt@cvs.openbsd.org 2001/12/24 07:29:43 + [ssh-add.c] + try all listed keys.. how did this get broken? + - markus@cvs.openbsd.org 2001/12/25 18:49:56 + [key.c] + be more careful on allocation + - markus@cvs.openbsd.org 2001/12/25 18:53:00 + [auth1.c] + be more carefull on allocation + - markus@cvs.openbsd.org 2001/12/27 18:10:29 + [ssh-keygen.c] + -t is only needed for key generation (unbreaks -i, -e, etc). + - markus@cvs.openbsd.org 2001/12/27 18:22:16 + [auth1.c authfile.c auth-rsa.c dh.c kexdh.c kexgex.c key.c rsa.c] + [scard.c ssh-agent.c sshconnect1.c sshd.c ssh-dss.c] + call fatal() for openssl allocation failures + - stevesk@cvs.openbsd.org 2001/12/27 18:22:53 + [sshd.8] + clarify -p; ok markus@ + - markus@cvs.openbsd.org 2001/12/27 18:26:13 + [authfile.c] + missing include + - markus@cvs.openbsd.org 2001/12/27 19:37:23 + [dh.c kexdh.c kexgex.c] + always use BN_clear_free instead of BN_free + - markus@cvs.openbsd.org 2001/12/27 19:54:53 + [auth1.c auth.h auth-rh-rsa.c] + auth_rhosts_rsa now accept generic keys. + - markus@cvs.openbsd.org 2001/12/27 20:39:58 + [auth1.c auth-rsa.c channels.c clientloop.c packet.c packet.h] + [serverloop.c session.c ssh.c sshconnect1.c sshd.c ttymodes.c] + get rid of packet_integrity_check, use packet_done() instead. + - markus@cvs.openbsd.org 2001/12/28 12:14:27 + [auth1.c auth2.c auth2-chall.c auth-rsa.c channels.c clientloop.c] + [kex.c kexdh.c kexgex.c packet.c packet.h serverloop.c session.c] + [ssh.c sshconnect1.c sshconnect2.c sshd.c] + s/packet_done/packet_check_eom/ (end-of-message); ok djm@ + - markus@cvs.openbsd.org 2001/12/28 13:57:33 + [auth1.c kexdh.c kexgex.c packet.c packet.h sshconnect1.c sshd.c] + packet_get_bignum* no longer returns a size + - markus@cvs.openbsd.org 2001/12/28 14:13:13 + [bufaux.c bufaux.h packet.c] + buffer_get_bignum: int -> void + - markus@cvs.openbsd.org 2001/12/28 14:50:54 + [auth1.c auth-rsa.c channels.c dispatch.c kex.c kexdh.c kexgex.c] + [packet.c packet.h serverloop.c session.c ssh.c sshconnect1.c] + [sshconnect2.c sshd.c] + packet_read* no longer return the packet length, since it's not used. + - markus@cvs.openbsd.org 2001/12/28 15:06:00 + [auth2.c auth2-chall.c channels.c channels.h clientloop.c dispatch.c] + [dispatch.h kex.c kex.h serverloop.c ssh.c sshconnect2.c] + remove plen from the dispatch fn. it's no longer used. + - stevesk@cvs.openbsd.org 2001/12/28 22:37:48 + [ssh.1 sshd.8] + document LogLevel DEBUG[123]; ok markus@ + - stevesk@cvs.openbsd.org 2001/12/29 21:56:01 + [authfile.c channels.c compress.c packet.c sftp-server.c] + [ssh-agent.c ssh-keygen.c] + remove unneeded casts and some char->u_char cleanup; ok markus@ + - stevesk@cvs.openbsd.org 2002/01/03 04:11:08 + [ssh_config] + grammar in comment + - stevesk@cvs.openbsd.org 2002/01/04 17:59:17 + [readconf.c servconf.c] + remove #ifdef _PATH_XAUTH/#endif; ok markus@ + - stevesk@cvs.openbsd.org 2002/01/04 18:14:16 + [servconf.c sshd.8] + protocol 2 HostKey code default is now /etc/ssh_host_rsa_key and + /etc/ssh_host_dsa_key like we have in sshd_config. ok markus@ + - markus@cvs.openbsd.org 2002/01/05 10:43:40 + [channels.c] + fix hanging x11 channels for rejected cookies (e.g. + XAUTHORITY=/dev/null xbiff) bug #36, based on patch from + djast@cs.toronto.edu + - stevesk@cvs.openbsd.org 2002/01/05 21:51:56 + [ssh.1 sshd.8] + some missing and misplaced periods + - markus@cvs.openbsd.org 2002/01/09 13:49:27 + [ssh-keygen.c] + append \n only for public keys + - markus@cvs.openbsd.org 2002/01/09 17:16:00 + [channels.c] + merge channel_pre_open_15/channel_pre_open_20; ok provos@ + - markus@cvs.openbsd.org 2002/01/09 17:26:35 + [channels.c nchan.c] + replace buffer_consume(b, buffer_len(b)) with buffer_clear(b); + ok provos@ + - markus@cvs.openbsd.org 2002/01/10 11:13:29 + [serverloop.c] + skip client_alive_check until there are channels; ok beck@ + - markus@cvs.openbsd.org 2002/01/10 11:24:04 + [clientloop.c] + handle SSH2_MSG_GLOBAL_REQUEST (just reply with failure); ok djm@ + - markus@cvs.openbsd.org 2002/01/10 12:38:26 + [nchan.c] + remove dead code (skip drain) + - markus@cvs.openbsd.org 2002/01/10 12:47:59 + [nchan.c] + more unused code (with channels.c:1.156) + - markus@cvs.openbsd.org 2002/01/11 10:31:05 + [packet.c] + handle received SSH2_MSG_UNIMPLEMENTED messages; ok djm@ + - markus@cvs.openbsd.org 2002/01/11 13:36:43 + [ssh2.h] + add defines for msg type ranges + - markus@cvs.openbsd.org 2002/01/11 13:39:36 + [auth2.c dispatch.c dispatch.h kex.c] + a single dispatch_protocol_error() that sends a message of + type 'UNIMPLEMENTED' + dispatch_range(): set handler for a ranges message types + use dispatch_protocol_ignore() for authentication requests after + successful authentication (the drafts requirement). + serverloop/clientloop now send a 'UNIMPLEMENTED' message instead + of exiting. + - markus@cvs.openbsd.org 2002/01/11 20:14:11 + [auth2-chall.c auth-skey.c] + use strlcpy not strlcat; mouring@ + - markus@cvs.openbsd.org 2002/01/11 23:02:18 + [readpass.c] + use _PATH_TTY + - markus@cvs.openbsd.org 2002/01/11 23:02:51 + [auth2-chall.c] + use snprintf; mouring@ + - markus@cvs.openbsd.org 2002/01/11 23:26:30 + [auth-skey.c] + use snprintf; mouring@ + - markus@cvs.openbsd.org 2002/01/12 13:10:29 + [auth-skey.c] + undo local change + - provos@cvs.openbsd.org 2002/01/13 17:27:07 + [ssh-agent.c] + change to use queue.h macros; okay markus@ + - markus@cvs.openbsd.org 2002/01/13 17:57:37 + [auth2.c auth2-chall.c compat.c sshconnect2.c sshd.c] + use buffer API and avoid static strings of fixed size; + ok provos@/mouring@ + - markus@cvs.openbsd.org 2002/01/13 21:31:20 + [channels.h nchan.c] + add chan_set_[io]state(), order states, state is now an u_int, + simplifies debugging messages; ok provos@ + - markus@cvs.openbsd.org 2002/01/14 13:22:35 + [nchan.c] + chan_send_oclose1() no longer calls chan_shutdown_write(); ok provos@ + - markus@cvs.openbsd.org 2002/01/14 13:34:07 + [nchan.c] + merge chan_[io]buf_empty[12]; ok provos@ + - markus@cvs.openbsd.org 2002/01/14 13:40:10 + [nchan.c] + correct fn names for ssh2, do not switch from closed to closed; + ok provos@ + - markus@cvs.openbsd.org 2002/01/14 13:41:13 + [nchan.c] + remove duplicated code; ok provos@ + - markus@cvs.openbsd.org 2002/01/14 13:55:55 + [channels.c channels.h nchan.c] + remove function pointers for events, remove chan_init*; ok provos@ + - markus@cvs.openbsd.org 2002/01/14 13:57:03 + [channels.h nchan.c] + (c) 2002 + - markus@cvs.openbsd.org 2002/01/16 13:17:51 + [channels.c channels.h serverloop.c ssh.c] + wrapper for channel_setup_fwd_listener + - stevesk@cvs.openbsd.org 2002/01/16 17:40:23 + [sshd_config] + The stategy now 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. Subsystem is currently the only default option + changed. ok markus@ + - stevesk@cvs.openbsd.org 2002/01/16 17:42:33 + [ssh.1] + correct defaults for -i/IdentityFile; ok markus@ + - stevesk@cvs.openbsd.org 2002/01/16 17:55:33 + [ssh_config] + correct some commented defaults. add Ciphers default. ok markus@ + - stevesk@cvs.openbsd.org 2002/01/17 04:27:37 + [log.c] + casts to silence enum type warnings for bugzilla bug 37; ok markus@ + - stevesk@cvs.openbsd.org 2002/01/18 17:14:16 + [sshd.8] + correct Ciphers default; paola.mannaro@ubs.com + - stevesk@cvs.openbsd.org 2002/01/18 18:14:17 + [authfd.c bufaux.c buffer.c cipher.c packet.c ssh-agent.c ssh-keygen.c] + unneeded cast cleanup; ok markus@ + - stevesk@cvs.openbsd.org 2002/01/18 20:46:34 + [sshd.8] + clarify Allow(Groups|Users) and Deny(Groups|Users); suggestion from + allard@oceanpark.com; ok markus@ + - markus@cvs.openbsd.org 2002/01/21 15:13:51 + [sshconnect.c] + use read_passphrase+ECHO in confirm(), allows use of ssh-askpass + for hostkey confirm. + - markus@cvs.openbsd.org 2002/01/21 22:30:12 + [cipher.c compat.c myproposal.h] + remove "rijndael-*", just use "aes-" since this how rijndael is called + in the drafts; ok stevesk@ + - markus@cvs.openbsd.org 2002/01/21 23:27:10 + [channels.c nchan.c] + cleanup channels faster if the are empty and we are in drain-state; + ok deraadt@ + - stevesk@cvs.openbsd.org 2002/01/22 02:52:41 + [servconf.c] + typo in error message; from djast@cs.toronto.edu + - (djm) Make auth2-pam.c compile again after dispatch.h and packet.h + changes + - (djm) Recent Glibc includes an incompatible sys/queue.h. Treat it as + bogus in configure + - (djm) Use local sys/queue.h if necessary in ssh-agent.c + +20020121 + - (djm) Rework ssh-rand-helper: + - Reduce quantity of ifdef code, in preparation for ssh_rand_conf + - Always seed from system calls, even when doing PRNGd seeding + - Tidy and comment #define knobs + - Remove unused facility for multiple runs through command list + - KNF, cleanup, update copyright + +20020114 + - (djm) Bug #50 - make autoconf entropy path checks more robust + +20020108 + - (djm) Merge Cygwin copy_environment with do_pam_environment, removing + fixed env var size limit in the process. Report from Corinna Vinschen + + - (stevesk) defines.h: use "/var/spool/sockets/X11/%u" for HP-UX. does + not depend on transition links. from Lutz Jaenicke. + +20020106 + - (stevesk) defines.h: determine _PATH_UNIX_X; currently "/tmp/.X11-unix/X%u" + for all platforms except HP-UX, which is "/usr/spool/sockets/X11/%u". + +20020105 + - (bal) NCR requies use_pipes to operate correctly. + - (stevesk) fix spurious ; from NCR change. + +20020103 + - (djm) Use bigcrypt() on systems with SCO_PROTECTED_PW. Patch from + Roger Cornelius + +20011229 + - (djm) Apply Cygwin pointer deref fix from Corinna Vinschen + Could be abused to guess valid usernames + - (djm) Typo in contrib/cygwin/README Fix from Corinna Vinschen + + +20011228 + - (djm) Remove recommendation to use GNU make, we should support most + make programs. + +20011225 + - (stevesk) [Makefile.in ssh-rand-helper.c] + portable lib and __progname support for ssh-rand-helper; ok djm@ + +20011223 + - (bal) Removed contrib/chroot.diff and noted in contrib/README that it + was not being maintained. + +20011222 + - (djm) Ignore fix & patchlevel in OpenSSL version check. Patch from + solar@openwall.com + - (djm) Rework entropy code. If the OpenSSL PRNG is has not been + internally seeded, execute a subprogram "ssh-rand-helper" to obtain + some entropy for us. Rewrite the old in-process entropy collecter as + an example ssh-rand-helper. + - (djm) Always perform ssh_prng_cmds path lookups in configure, even if + we don't end up using ssh_prng_cmds (so we always get a valid file) + +20011221 + - (djm) Add option to gnome-ssh-askpass to stop it from grabbing the X + server. I have found this necessary to avoid server hangs with X input + extensions (e.g. kinput2). Enable by setting the environment variable + "GNOME_SSH_ASKPASS_NOGRAB" + - OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2001/12/08 17:49:28 + [channels.c pathnames.h] + use only one path to X11 UNIX domain socket vs. an array of paths + to try. report from djast@cs.toronto.edu. ok markus@ + - markus@cvs.openbsd.org 2001/12/09 18:45:56 + [auth2.c auth2-chall.c auth.h] + add auth2_challenge_stop(), simplifies cleanup of kbd-int sessions, + fixes memleak. + - stevesk@cvs.openbsd.org 2001/12/10 16:45:04 + [sshd.c] + possible fd leak on error; ok markus@ + - markus@cvs.openbsd.org 2001/12/10 20:34:31 + [ssh-keyscan.c] + check that server supports v1 for -t rsa1, report from wirth@dfki.de + - jakob@cvs.openbsd.org 2001/12/18 10:04:21 + [auth.h hostfile.c hostfile.h] + remove auth_rsa_read_key, make hostfile_ready_key non static; ok markus@ + - jakob@cvs.openbsd.org 2001/12/18 10:05:15 + [auth2.c] + log fingerprint on successful public key authentication; ok markus@ + - jakob@cvs.openbsd.org 2001/12/18 10:06:24 + [auth-rsa.c] + log fingerprint on successful public key authentication, simplify + usage of key structs; ok markus@ + - deraadt@cvs.openbsd.org 2001/12/19 07:18:56 + [auth1.c auth2.c auth2-chall.c auth-bsdauth.c auth.c authfile.c auth.h] + [auth-krb4.c auth-rhosts.c auth-skey.c bufaux.c canohost.c channels.c] + [cipher.c clientloop.c compat.c compress.c deattack.c key.c log.c mac.c] + [match.c misc.c nchan.c packet.c readconf.c rijndael.c rijndael.h scard.c] + [servconf.c servconf.h serverloop.c session.c sftp.c sftp-client.c] + [sftp-glob.c sftp-int.c sftp-server.c ssh-add.c ssh-agent.c ssh.c] + [sshconnect1.c sshconnect2.c sshconnect.c sshd.8 sshd.c sshd_config] + [ssh-keygen.c sshlogin.c sshpty.c sshtty.c ttymodes.c uidswap.c] + basic KNF done while i was looking for something else + - markus@cvs.openbsd.org 2001/12/19 16:09:39 + [serverloop.c] + fix race between SIGCHLD and select with an additional pipe. writing + to the pipe on SIGCHLD wakes up select(). using pselect() is not + portable and siglongjmp() ugly. W. R. Stevens suggests similar solution. + initial idea by pmenage@ensim.com; ok deraadt@, djm@ + - stevesk@cvs.openbsd.org 2001/12/19 17:16:13 + [authfile.c bufaux.c bufaux.h buffer.c buffer.h packet.c packet.h ssh.c] + change the buffer/packet interface to use void* vs. char*; ok markus@ + - markus@cvs.openbsd.org 2001/12/20 16:37:29 + [channels.c channels.h session.c] + setup x11 listen socket for just one connect if the client requests so. + (v2 only, but the openssh client does not support this feature). + - djm@cvs.openbsd.org 2001/12/20 22:50:24 + [auth2.c auth2-chall.c channels.c channels.h clientloop.c dispatch.c] + [dispatch.h kex.c kex.h packet.c packet.h serverloop.c ssh.c] + [sshconnect2.c] + Conformance fix: we should send failing packet sequence number when + responding with a SSH_MSG_UNIMPLEMENTED message. Spotted by + yakk@yakk.dot.net; ok markus@ + +20011219 + - (stevesk) OpenBSD CVS sync X11 localhost display + - stevesk@cvs.openbsd.org 2001/11/29 14:10:51 + [channels.h channels.c session.c] + sshd X11 fake server will now listen on localhost by default: + $ echo $DISPLAY + localhost:12.0 + $ netstat -an|grep 6012 + tcp 0 0 127.0.0.1.6012 *.* LISTEN + tcp6 0 0 ::1.6012 *.* LISTEN + sshd_config gatewayports=yes can be used to revert back to the old + behavior. will control this with another option later. ok markus@ + - stevesk@cvs.openbsd.org 2001/12/19 08:43:11 + [includes.h session.c] + handle utsname.nodename case for FamilyLocal X authorization; ok markus@ + +20011207 + - (bal) PCRE no longer required. Banished from the source along with + fake-regex.h + - (bal) OpenBSD CVS Sync + - stevesk@cvs.openbsd.org 2001/12/06 18:02:32 + [channels.c sshconnect.c] + shutdown(sock, SHUT_RDWR) not needed here; ok markus@ + - stevesk@cvs.openbsd.org 2001/12/06 18:09:23 + [channels.c session.c] + strncpy->strlcpy. remaining strncpy's are necessary. ok markus@ + - stevesk@cvs.openbsd.org 2001/12/06 18:20:32 + [channels.c] + disable nagle for X11 fake server and client TCPs. from netbsd. + ok markus@ + +20011206 + - (bal) OpenBSD CVS Sync + - deraadt@cvs.openbsd.org 2001/11/14 20:45:08 + [sshd.c] + errno saving wrapping in a signal handler + - markus@cvs.openbsd.org 2001/11/16 12:46:13 + [ssh-keyscan.c] + handle empty lines instead of dumping core; report from sha@sha-1.net + - stevesk@cvs.openbsd.org 2001/11/17 19:14:34 + [auth2.c auth.c readconf.c servconf.c ssh-agent.c ssh-keygen.c] + enum/int type cleanup where it made sense to do so; ok markus@ + - markus@cvs.openbsd.org 2001/11/19 11:20:21 + [sshd.c] + fd leak on HUP; ok stevesk@ + - stevesk@cvs.openbsd.org 2001/11/19 18:40:46 + [ssh-agent.1] + clarify/state that private keys are not exposed to clients using the + agent; ok markus@ + - mpech@cvs.openbsd.org 2001/11/19 19:02:16 + [deattack.c radix.c] + kill more registers + millert@ ok + - markus@cvs.openbsd.org 2001/11/21 15:51:24 + [key.c] + mem leak + - stevesk@cvs.openbsd.org 2001/11/21 18:49:14 + [ssh-keygen.1] + more on passphrase construction; ok markus@ + - stevesk@cvs.openbsd.org 2001/11/22 05:27:29 + [ssh-keyscan.c] + don't use "\n" in fatal() + - markus@cvs.openbsd.org 2001/11/22 12:34:22 + [clientloop.c serverloop.c sshd.c] + volatile sig_atomic_t + - stevesk@cvs.openbsd.org 2001/11/29 19:06:39 + [channels.h] + remove dead function prototype; ok markus@ + - markus@cvs.openbsd.org 2001/11/29 22:08:48 + [auth-rsa.c] + fix protocol error: send 'failed' message instead of a 2nd challenge + (happens if the same key is in authorized_keys twice). + reported Ralf_Meister@genua.de; ok djm@ + - stevesk@cvs.openbsd.org 2001/11/30 20:39:28 + [ssh.c] + sscanf() length dependencies are clearer now; can also shrink proto + and data if desired, but i have not done that. ok markus@ + - markus@cvs.openbsd.org 2001/12/01 21:41:48 + [session.c sshd.8] + don't pass user defined variables to /usr/bin/login + - deraadt@cvs.openbsd.org 2001/12/02 02:08:32 + [sftp-common.c] + zap }; + - itojun@cvs.openbsd.org 2001/12/05 03:50:01 + [clientloop.c serverloop.c sshd.c] + deal with LP64 printf issue with sig_atomic_t. from thorpej + - itojun@cvs.openbsd.org 2001/12/05 03:56:39 + [auth1.c auth2.c canohost.c channels.c deattack.c packet.c scp.c + sshconnect2.c] + make it compile with more strict prototype checking + - deraadt@cvs.openbsd.org 2001/12/05 10:06:12 + [authfd.c authfile.c bufaux.c channels.c compat.c kex.c kexgex.c + key.c misc.c packet.c servconf.c ssh-agent.c sshconnect2.c + sshconnect.c sshd.c ssh-dss.c ssh-keygen.c ssh-rsa.c] + minor KNF + - markus@cvs.openbsd.org 2001/12/05 15:04:48 + [version.h] + post 3.0.2 + - markus@cvs.openbsd.org 2001/12/05 16:54:51 + [compat.c match.c match.h] + make theo and djm happy: bye bye regexp + - markus@cvs.openbsd.org 2001/12/06 13:30:06 + [servconf.c servconf.h sshd.8 sshd.c] + add -o to sshd, too. ok deraadt@ + - (bal) Minor white space fix up in servconf.c + +20011126 + - (tim) [contrib/cygwin/README, openbsd-compat/bsd-cygwin_util.c, + openbsd-compat/bsd-cygwin_util.h, openbsd-compat/daemon.c] + Allow SSHD to install as service under WIndows 9x/Me + [configure.ac] Fix to allow linking against PCRE on Cygwin + Patches by Corinna Vinschen 20011115 - (djm) Fix IPv4 default in ssh-keyscan. Spotted by Dan Astoorian diff --git a/openssh/INSTALL b/openssh/INSTALL index 777bdfe..c6ee3c8 100644 --- a/openssh/INSTALL +++ b/openssh/INSTALL @@ -45,18 +45,6 @@ lacks /dev/random and don't want to use OpenSSH's internal entropy collection. http://www.lothar.com/tech/crypto/ -GNU Make: -ftp://ftp.gnu.org/gnu/make/ - -OpenSSH has only been tested with GNU make. It may work with other -'make' programs, but you are on your own. - -PCRE (PERL-compatible Regular Expression library): -ftp://ftp.cus.cam.ac.uk/pub/software/programing/pcre/ - -Most platforms do not require this. However older Unices may not have a -posix regex library. PCRE provides a POSIX interface. - S/Key Libraries: http://www.sparc.spb.su/solaris/skey/ diff --git a/openssh/LICENCE b/openssh/LICENCE index b229fcd..1c98a1d 100644 --- a/openssh/LICENCE +++ b/openssh/LICENCE @@ -140,8 +140,46 @@ OpenSSH contains no GPL code. * 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: diff --git a/openssh/Makefile.in b/openssh/Makefile.in index d20bfca..5bc3cb0 100644 --- a/openssh/Makefile.in +++ b/openssh/Makefile.in @@ -19,17 +19,20 @@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server -PATHS= -DETCDIR=\"$(sysconfdir)\" \ +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_PIDDIR=\"$(piddir)\" + -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ + -DSSH_RAND_HELPER=\"$(libexecdir)/ssh-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@ @@ -41,12 +44,13 @@ EXEEXT=@EXEEXT@ SSH_MODE= @SSHMODE@ 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-agent$(EXEEXT) scp$(EXEEXT) $(SFTP_PROGS) +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${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 mac.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 ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o +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 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 ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o @@ -60,17 +64,17 @@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out CONFIGFILES_IN=sshd_config ssh_config moduli PATHSUBS = \ - -D/etc/ssh_config=$(sysconfdir)/ssh_config \ - -D/etc/ssh_known_hosts=$(sysconfdir)/ssh_known_hosts \ - -D/etc/sshd_config=$(sysconfdir)/sshd_config \ + -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_host_key=$(sysconfdir)/ssh_host_key \ - -D/etc/ssh_host_dsa_key=$(sysconfdir)/ssh_host_dsa_key \ - -D/etc/ssh_host_rsa_key=$(sysconfdir)/ssh_host_rsa_key \ + -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/moduli=$(sysconfdir)/moduli \ - -D/etc/sshrc=$(sysconfdir)/sshrc \ + -D/etc/ssh/moduli=$(sysconfdir)/moduli \ + -D/etc/ssh/sshrc=$(sysconfdir)/sshrc \ -D/usr/X11R6/bin/xauth=$(XAUTH_PATH) \ -D/usr/bin:/bin:/usr/sbin:/sbin=@user_path@ @@ -98,7 +102,7 @@ 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 $(LIBS) + $(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) @@ -121,6 +125,9 @@ sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o 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) @@ -197,6 +204,9 @@ install-files: scard-install $(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 @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 @@ -212,7 +222,6 @@ install-files: scard-install 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 - #@FILEPRIV@ -f dev,filesys,driver $(DESTDIR)$(bindir)/ssh $(DESTDIR)$(bindir)/slogin if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \ $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \ fi diff --git a/openssh/README b/openssh/README index 979d1d5..75269c8 100644 --- a/openssh/README +++ b/openssh/README @@ -1,6 +1,6 @@ - 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 +- Thanks to HARUYAMA Seigo This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other Unices. diff --git a/openssh/TODO b/openssh/TODO index 3c89852..11abaf6 100644 --- a/openssh/TODO +++ b/openssh/TODO @@ -75,6 +75,10 @@ Clean up configure/makefiles: - 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. diff --git a/openssh/acconfig.h b/openssh/acconfig.h index 436d72e..8382c85 100644 --- a/openssh/acconfig.h +++ b/openssh/acconfig.h @@ -59,9 +59,6 @@ /* Define if you are on Cygwin */ #undef HAVE_CYGWIN -/* Define if you lack native POSIX regex and you are using PCRE */ -#undef HAVE_LIBPCRE - /* Define if you have a broken realpath. */ #undef BROKEN_REALPATH @@ -89,9 +86,6 @@ /* Define if you want IRIX kernel jobs */ #undef WITH_IRIX_JOBS -/* Location of random number pool */ -#undef RANDOM_POOL - /* Location of PRNGD/EGD random number socket */ #undef PRNGD_SOCKET @@ -263,9 +257,6 @@ #undef HAVE_SS_FAMILY_IN_SS #undef HAVE___SS_FAMILY_IN_SS -/* Define if you have a regcomp() function */ -#undef HAVE_REGCOMP - /* Define if you have /dev/ptmx */ #undef HAVE_DEV_PTMX @@ -329,6 +320,9 @@ /* Define if you want smartcard support */ #undef SMARTCARD +/* Define if you want to use OpenSSL's internally seeded PRNG only */ +#undef OPENSSL_PRNG_ONLY + @BOTTOM@ /* ******************* Shouldn't need to edit below this line ************** */ diff --git a/openssh/auth-bsdauth.c b/openssh/auth-bsdauth.c index 3732477..b70d48f 100644 --- a/openssh/auth-bsdauth.c +++ b/openssh/auth-bsdauth.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: auth-bsdauth.c,v 1.1 2001/05/18 14:13:28 markus Exp $"); +RCSID("$OpenBSD: auth-bsdauth.c,v 1.2 2001/12/19 07:18:56 deraadt Exp $"); #ifdef BSD_AUTH #include "xmalloc.h" @@ -36,74 +36,74 @@ bsdauth_init_ctx(Authctxt *authctxt) } static int -bsdauth_query(void *ctx, char **name, char **infotxt, +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 *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->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; + 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; } static 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"); + Authctxt *authctxt = ctx; + int authok; + + if (authctxt->as == 0) + error("bsdauth_respond: no bsd auth session"); - if (numresponses != 1) - return -1; + if (numresponses != 1) + return -1; - authok = auth_userresponse(authctxt->as, responses[0], 0); - authctxt->as = NULL; - debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok); + authok = auth_userresponse(authctxt->as, responses[0], 0); + authctxt->as = NULL; + debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok); - return (authok == 0) ? -1 : 0; + return (authok == 0) ? -1 : 0; } static void bsdauth_free_ctx(void *ctx) { - Authctxt *authctxt = ctx; + Authctxt *authctxt = ctx; - if (authctxt && authctxt->as) { - auth_close(authctxt->as); - authctxt->as = NULL; - } + if (authctxt && authctxt->as) { + auth_close(authctxt->as); + authctxt->as = NULL; + } } KbdintDevice bsdauth_device = { diff --git a/openssh/auth-krb4.c b/openssh/auth-krb4.c index 031dcd3..f7a144f 100644 --- a/openssh/auth-krb4.c +++ b/openssh/auth-krb4.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-krb4.c,v 1.24 2001/06/26 16:15:22 dugsong Exp $"); +RCSID("$OpenBSD: auth-krb4.c,v 1.25 2001/12/19 07:18:56 deraadt Exp $"); #include "ssh.h" #include "ssh1.h" @@ -49,7 +49,7 @@ krb4_init(void *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); @@ -79,13 +79,13 @@ krb4_init(void *context) } /* 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); } @@ -103,10 +103,10 @@ auth_krb4_password(Authctxt *authctxt, const char *password) 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. @@ -128,7 +128,7 @@ auth_krb4_password(Authctxt *authctxt, const char *password) } /* Successful authentication. */ chown(tkt_string(), pw->pw_uid, pw->pw_gid); - + /* * Now that we have a TGT, try to get a local * "rcmd" ticket to ensure that we are not talking @@ -138,7 +138,7 @@ auth_krb4_password(Authctxt *authctxt, const char *password) 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)) == NULL) { log("Couldn't get local host address!"); @@ -146,7 +146,7 @@ auth_krb4_password(Authctxt *authctxt, const char *password) } memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr)); - + /* Verify our "rcmd" ticket. */ r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, faddr, &adata, ""); @@ -186,13 +186,13 @@ auth_krb4_password(Authctxt *authctxt, const char *password) } else /* Logging in as root or no local Kerberos realm. */ debug("Unable to authenticate to Kerberos."); - + failure: krb4_cleanup_proc(authctxt); - + if (!options.kerberos_or_local_passwd) return (0); - + /* Fall back to ordinary passwd authentication. */ return (-1); } @@ -220,9 +220,9 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client) socklen_t slen; u_int cksum; int r, s; - + s = packet_get_connection_in(); - + slen = sizeof(local); memset(&local, 0, sizeof(local)); if (getsockname(s, (struct sockaddr *) & local, &slen) < 0) @@ -235,7 +235,7 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client) } instance[0] = '*'; instance[1] = 0; - + /* Get the encrypted request, challenge, and session key. */ if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) { @@ -243,11 +243,11 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client) return (0); } des_key_sched((des_cblock *) adat.session, schedule); - + *client = xmalloc(MAX_K_NAME_SZ); (void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname, *adat.pinst ? "." : "", adat.pinst, adat.prealm); - + /* Check ~/.klogin authorization now. */ if (kuserok(&adat, authctxt->user) != KSUCCESS) { log("Kerberos v4 .klogin authorization failed for %s to " @@ -259,7 +259,7 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client) session key. */ cksum = adat.checksum + 1; cksum = htonl(cksum); - + /* If we can't successfully encrypt the checksum, we send back an empty message, admitting our failure. */ if ((r = krb_mk_priv((u_char *) & cksum, reply.dat, sizeof(cksum) + 1, @@ -269,10 +269,10 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client) reply.length = 0; } else reply.length = r; - + /* Clear session key. */ memset(&adat.session, 0, sizeof(&adat.session)); - + packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE); packet_put_string((char *) reply.dat, reply.length); packet_send(); @@ -287,19 +287,19 @@ 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 (!radix_to_creds(string, &creds)) { 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, @@ -308,10 +308,10 @@ auth_krb4_tgt(Authctxt *authctxt, const char *string) } if (!krb4_init(authctxt)) goto failure; - + if (in_tkt(creds.pname, creds.pinst) != KSUCCESS) goto failure; - + if (save_credentials(creds.service, creds.instance, creds.realm, creds.session, creds.lifetime, creds.kvno, &creds.ticket_st, creds.issue_date) != KSUCCESS) { @@ -320,20 +320,20 @@ auth_krb4_tgt(Authctxt *authctxt, const char *string) } /* Successful authentication, passed all checks. */ chown(tkt_string(), pw->pw_uid, pw->pw_gid); - + debug("Kerberos v4 TGT accepted (%s%s%s@%s)", creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm); memset(&creds, 0, sizeof(creds)); - + restore_uid(); - + return (1); - + failure: krb4_cleanup_proc(authctxt); memset(&creds, 0, sizeof(creds)); restore_uid(); - + return (0); } @@ -343,22 +343,22 @@ auth_afs_token(Authctxt *authctxt, const char *token_string) CREDENTIALS creds; struct passwd *pw; uid_t uid; - + if ((pw = authctxt->pw) == NULL) return (0); - + if (!radix_to_creds(token_string, &creds)) { log("Protocol error decoding AFS token"); return (0); } if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */ strlcpy(creds.service, "afs", sizeof creds.service); - + if (strncmp(creds.pname, "AFS ID ", 7) == 0) uid = atoi(creds.pname + 7); else 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); @@ -367,7 +367,7 @@ auth_afs_token(Authctxt *authctxt, const char *token_string) } debug("AFS token accepted (%s@%s)", creds.pname, creds.realm); memset(&creds, 0, sizeof(creds)); - + return (1); } #endif /* AFS */ diff --git a/openssh/auth-krb5.c b/openssh/auth-krb5.c index b56f43a..2da0669 100644 --- a/openssh/auth-krb5.c +++ b/openssh/auth-krb5.c @@ -2,10 +2,11 @@ * Kerberos v5 authentication and ticket-passing routines. * * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $ - * $OpenBSD: auth-krb5.c,v 1.2 2001/11/12 01:47:09 dugsong Exp $ */ #include "includes.h" +RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $"); + #include "ssh.h" #include "ssh1.h" #include "packet.h" @@ -26,7 +27,7 @@ krb5_init(void *context) Authctxt *authctxt = (Authctxt *)context; krb5_error_code problem; static int cleanup_registered = 0; - + if (authctxt->krb5_ctx == NULL) { problem = krb5_init_context(&authctxt->krb5_ctx); if (problem) @@ -45,7 +46,7 @@ krb5_init(void *context) * only, in auth is received ticket, in client is returned principal * from the ticket */ -int +int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) { krb5_error_code problem; @@ -58,52 +59,52 @@ auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) server = NULL; ticket = NULL; reply.length = 0; - + problem = krb5_init(authctxt); - if (problem) + 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(); problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, &fd); if (problem) goto err; - + problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL , KRB5_NT_SRV_HST, &server); if (problem) goto err; - + problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx, auth, server, NULL, NULL, &ticket); if (problem) goto err; - + problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client, &authctxt->krb5_user); if (problem) goto err; - + /* if client wants mutual auth */ 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(); @@ -117,10 +118,15 @@ auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) krb5_free_ticket(authctxt->krb5_ctx, ticket); if (reply.length) xfree(reply.data); - - if (problem) - debug("Kerberos v5 authentication failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); + + 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); } @@ -131,51 +137,51 @@ auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) krb5_error_code problem; krb5_ccache ccache = NULL; char *pname; - + if (authctxt->pw == NULL || authctxt->krb5_user == NULL) return (0); - + temporarily_use_uid(authctxt->pw); - + problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops, &ccache); if (problem) goto fail; - + problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) goto fail; - + problem = krb5_rd_cred2(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, ccache, tgt); if (problem) goto fail; - + 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); } @@ -183,47 +189,54 @@ int auth_krb5_password(Authctxt *authctxt, const char *password) { 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; - + 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; - + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - + out: restore_uid(); - + if (problem) { - debug("Kerberos password authentication failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); - + if (authctxt->krb5_ctx != NULL) + 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 @@ -236,7 +249,7 @@ void krb5_cleanup_proc(void *context) { Authctxt *authctxt = (Authctxt *)context; - + debug("krb5_cleanup_proc called"); if (authctxt->krb5_fwd_ccache) { krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); diff --git a/openssh/auth-options.c b/openssh/auth-options.c index 9f90437..8df6a6d 100644 --- a/openssh/auth-options.c +++ b/openssh/auth-options.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-options.c,v 1.20 2001/08/30 20:36:34 stevesk Exp $"); +RCSID("$OpenBSD: auth-options.c,v 1.21 2002/01/29 14:32:03 markus Exp $"); #include "packet.h" #include "xmalloc.h" @@ -170,7 +170,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) if (strncasecmp(opts, cp, strlen(cp)) == 0) { 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); diff --git a/openssh/auth-options.h b/openssh/auth-options.h index 3b2ce34..aa6270f 100644 --- a/openssh/auth-options.h +++ b/openssh/auth-options.h @@ -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.10 2001/06/26 17:27:22 markus Exp $ */ - #ifndef AUTH_OPTIONS_H #define AUTH_OPTIONS_H diff --git a/openssh/auth-pam.c b/openssh/auth-pam.c index 801c9eb..687c95c 100644 --- a/openssh/auth-pam.c +++ b/openssh/auth-pam.c @@ -360,7 +360,7 @@ void start_pam(const char *user) fatal("PAM initialisation failed[%d]: %.200s", pam_retval, PAM_STRERROR(__pamh, pam_retval)); - rhost = get_remote_name_or_ip(utmp_len, options.reverse_mapping_check); + 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); diff --git a/openssh/auth-passwd.c b/openssh/auth-passwd.c index 988297c..095b9ba 100644 --- a/openssh/auth-passwd.c +++ b/openssh/auth-passwd.c @@ -36,12 +36,11 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-passwd.c,v 1.23 2001/06/26 16:15:23 dugsong Exp $"); +RCSID("$OpenBSD: auth-passwd.c,v 1.24 2002/03/04 12:43:06 markus Exp $"); #if !defined(USE_PAM) && !defined(HAVE_OSF_SIA) #include "packet.h" -#include "xmalloc.h" #include "log.h" #include "servconf.h" #include "auth.h" @@ -212,7 +211,11 @@ auth_password(Authctxt *authctxt, const char *password) else encrypted_password = crypt(password, salt); # else +# ifdef HAVE_SCO_PROTECTED_PW + encrypted_password = bigcrypt(password, salt); +# else encrypted_password = crypt(password, salt); +# endif /* HAVE_SCO_PROTECTED_PW */ # endif /* __hpux */ #endif /* HAVE_MD5_PASSWORDS */ diff --git a/openssh/auth-rh-rsa.c b/openssh/auth-rh-rsa.c index 8a486b3..d1b7ae9 100644 --- a/openssh/auth-rh-rsa.c +++ b/openssh/auth-rh-rsa.c @@ -13,10 +13,9 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-rh-rsa.c,v 1.26 2001/11/07 22:41:51 markus Exp $"); +RCSID("$OpenBSD: auth-rh-rsa.c,v 1.29 2002/03/04 12:43:06 markus Exp $"); #include "packet.h" -#include "xmalloc.h" #include "uidswap.h" #include "log.h" #include "servconf.h" @@ -32,16 +31,15 @@ RCSID("$OpenBSD: auth-rh-rsa.c,v 1.26 2001/11/07 22:41:51 markus Exp $"); */ int -auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key) +auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key) { extern ServerOptions options; const char *canonical_hostname; HostStatus host_status; - Key *client_key; debug("Trying rhosts with RSA host authentication for client user %.100s", client_user); - if (pw == NULL || client_host_key == NULL) + if (pw == NULL || client_host_key == NULL || client_host_key->rsa == NULL) return 0; /* Check if we would accept it using rhosts authentication. */ @@ -49,21 +47,14 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key return 0; canonical_hostname = get_canonical_hostname( - options.reverse_mapping_check); + options.verify_reverse_mapping); debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname); - /* 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); - - host_status = check_key_in_hostfiles(pw, client_key, canonical_hostname, - _PATH_SSH_SYSTEM_HOSTFILE, + host_status = check_key_in_hostfiles(pw, client_host_key, + canonical_hostname, _PATH_SSH_SYSTEM_HOSTFILE, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); - key_free(client_key); - if (host_status != HOST_OK) { 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."); @@ -72,7 +63,7 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key /* A matching host key was found and is known. */ /* Perform the challenge-response dialog with the client for the host key. */ - if (!auth_rsa_challenge_dialog(client_host_key)) { + if (!auth_rsa_challenge_dialog(client_host_key->rsa)) { log("Client on %.800s failed to respond correctly to host authentication.", canonical_hostname); return 0; diff --git a/openssh/auth-rhosts.c b/openssh/auth-rhosts.c index 9ba64db..bd15261 100644 --- a/openssh/auth-rhosts.c +++ b/openssh/auth-rhosts.c @@ -14,10 +14,9 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-rhosts.c,v 1.24 2001/06/23 15:12:17 itojun Exp $"); +RCSID("$OpenBSD: auth-rhosts.c,v 1.27 2002/03/04 12:43:06 markus Exp $"); #include "packet.h" -#include "xmalloc.h" #include "uidswap.h" #include "pathnames.h" #include "log.h" @@ -156,7 +155,7 @@ 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; @@ -186,7 +185,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, * 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 +203,16 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, /* 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)) { + 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); + hostname, ipaddr); return 1; } - if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, client_user, - pw->pw_name)) { + 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); + hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); return 1; } } @@ -230,7 +229,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, } 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 ownership or modes for home directory.", pw->pw_name); packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.", @@ -242,7 +241,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, /* 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,7 +256,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, */ 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); diff --git a/openssh/auth-rsa.c b/openssh/auth-rsa.c index 701d8bd..f7ae03c 100644 --- a/openssh/auth-rsa.c +++ b/openssh/auth-rsa.c @@ -14,7 +14,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth-rsa.c,v 1.44 2001/07/23 18:14:58 stevesk Exp $"); +RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $"); #include #include @@ -31,6 +31,7 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.44 2001/07/23 18:14:58 stevesk Exp $"); #include "log.h" #include "servconf.h" #include "auth.h" +#include "hostfile.h" /* import */ extern ServerOptions options; @@ -65,14 +66,17 @@ auth_rsa_challenge_dialog(RSA *pk) u_char buf[32], mdbuf[16], response[16]; MD5_CTX md; u_int i; - int plen, len; + int len; - encrypted_challenge = BN_new(); - challenge = BN_new(); + if ((encrypted_challenge = BN_new()) == NULL) + fatal("auth_rsa_challenge_dialog: BN_new() failed"); + if ((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(); + if ((ctx = BN_CTX_new()) == NULL) + fatal("auth_rsa_challenge_dialog: BN_CTX_new() failed"); BN_mod(challenge, challenge, pk->n, ctx); BN_CTX_free(ctx); @@ -87,10 +91,10 @@ auth_rsa_challenge_dialog(RSA *pk) 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); @@ -128,7 +132,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) FILE *f; u_long linenum = 0; struct stat st; - RSA *pk; + Key *key; + char *fp; /* no user given */ if (pw == NULL) @@ -170,9 +175,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) /* Flag indicating whether authentication has succeeded. */ authenticated = 0; - pk = RSA_new(); - pk->e = BN_new(); - pk->n = BN_new(); + key = key_new(KEY_RSA1); /* * Go though the accepted keys, looking for the current key. If @@ -210,7 +213,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) options = NULL; /* Parse the key from the line. */ - if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) { + if (hostfile_read_key(&cp, &bits, key) == 0) { debug("%.100s, line %lu: non ssh1 key syntax", file, linenum); continue; @@ -218,14 +221,14 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) /* 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)) + 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. */ /* @@ -236,11 +239,15 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) continue; /* Perform the challenge-response dialog for this key. */ - if (!auth_rsa_challenge_dialog(pk)) { + if (!auth_rsa_challenge_dialog(key->rsa)) { /* Wrong response. */ verbose("Wrong response to RSA authentication challenge."); packet_send_debug("Wrong response to RSA authentication challenge."); - continue; + /* + * Break out of the loop. Otherwise we might send + * another challenge and break the protocol. + */ + break; } /* * Correct response. The client has been successfully @@ -251,6 +258,12 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) * otherwise continue searching. */ authenticated = 1; + + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(key), fp); + xfree(fp); + break; } @@ -261,7 +274,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) xfree(file); fclose(f); - RSA_free(pk); + key_free(key); if (authenticated) packet_send_debug("RSA authentication accepted."); diff --git a/openssh/auth-sia.c b/openssh/auth-sia.c index 4e947cd..8585f5d 100644 --- a/openssh/auth-sia.c +++ b/openssh/auth-sia.c @@ -29,7 +29,7 @@ auth_sia_password(char *user, char *pass) SIAENTITY *ent = NULL; const char *host; - host = get_canonical_hostname(options.reverse_mapping_check); + host = get_canonical_hostname(options.verify_reverse_mapping); if (!user || !pass) return(0); @@ -58,7 +58,7 @@ session_setup_sia(char *user, char *tty) SIAENTITY *ent = NULL; const char *host; - host = get_canonical_hostname (options.reverse_mapping_check); + host = get_canonical_hostname (options.verify_reverse_mapping); if (sia_ses_init(&ent, saved_argc, saved_argv, host, user, tty, 0, NULL) != SIASUCCESS) { diff --git a/openssh/auth-skey.c b/openssh/auth-skey.c index f921fc1..df19f75 100644 --- a/openssh/auth-skey.c +++ b/openssh/auth-skey.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: auth-skey.c,v 1.12 2001/05/18 14:13:28 markus Exp $"); +RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $"); #ifdef SKEY @@ -40,7 +40,7 @@ skey_init_ctx(Authctxt *authctxt) #define PROMPT "\nS/Key Password: " static int -skey_query(void *ctx, char **name, char **infotxt, +skey_query(void *ctx, char **name, char **infotxt, u_int* numprompts, char ***prompts, u_int **echo_on) { Authctxt *authctxt = ctx; @@ -60,8 +60,7 @@ skey_query(void *ctx, char **name, char **infotxt, len = strlen(challenge) + strlen(PROMPT) + 1; p = xmalloc(len); - p[0] = '\0'; - strlcat(p, challenge, len); + strlcpy(p, challenge, len); strlcat(p, PROMPT, len); (*prompts)[0] = p; @@ -72,9 +71,9 @@ static int skey_respond(void *ctx, u_int numresponses, char **responses) { Authctxt *authctxt = ctx; - + if (authctxt->valid && - numresponses == 1 && + numresponses == 1 && skey_haskey(authctxt->pw->pw_name) == 0 && skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1) return 0; diff --git a/openssh/auth.c b/openssh/auth.c index 2bf877d..26dce5b 100644 --- a/openssh/auth.c +++ b/openssh/auth.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth.c,v 1.29 2001/11/08 20:02:24 markus Exp $"); +RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $"); #ifdef HAVE_LOGIN_H #include @@ -105,43 +105,60 @@ allowed_user(struct passwd * pw) 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 (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) { + 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.reverse_mapping_check); + 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_user(pw->pw_name, hostname, ipaddr, - 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_user(pw->pw_name, hostname, ipaddr, + 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; } /* @@ -152,6 +169,8 @@ allowed_user(struct passwd * pw) 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(); @@ -272,7 +291,7 @@ expand_filename(const char *filename, struct passwd *pw) } if (cp[0] == '%' && cp[1] == 'u') { buffer_append(&buffer, pw->pw_name, - strlen(pw->pw_name)); + strlen(pw->pw_name)); cp++; continue; } @@ -315,7 +334,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, Key *found; char *user_hostfile; struct stat st; - int host_status; + HostStatus host_status; /* Check if we know the host and its host key. */ found = key_new(key->type); @@ -326,7 +345,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, if (options.strict_modes && (stat(user_hostfile, &st) == 0) && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || - (st.st_mode & 022) != 0)) { + (st.st_mode & 022) != 0)) { log("Authentication refused for %.100s: " "bad owner or modes for %.200s", pw->pw_name, user_hostfile); @@ -399,7 +418,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, if (stat(buf, &st) < 0 || (st.st_uid != 0 && st.st_uid != uid) || (st.st_mode & 022) != 0) { - snprintf(err, errlen, + snprintf(err, errlen, "bad ownership or modes for directory %s", buf); return -1; } diff --git a/openssh/auth.h b/openssh/auth.h index edfc9fb..c717540 100644 --- a/openssh/auth.h +++ b/openssh/auth.h @@ -1,3 +1,5 @@ +/* $OpenBSD: auth.h,v 1.29 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -21,8 +23,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: auth.h,v 1.22 2001/06/26 17:27:22 markus Exp $ */ + #ifndef AUTH_H #define AUTH_H @@ -71,30 +73,28 @@ struct Authctxt { /* * Keyboard interactive device: - * init_ctx returns: non NULL upon success - * query returns: 0 - success, otherwise failure + * 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) __P((Authctxt*)); - int (*query) __P((void *ctx, char **name, char **infotxt, - u_int *numprompts, char ***prompts, - u_int **echo_on)); - int (*respond) __P((void *ctx, u_int numresp, char **responses)); - void (*free_ctx) __P((void *ctx)); + 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); }; int auth_rhosts(struct passwd *, const char *); int auth_rhosts2(struct passwd *, const char *, const char *, const char *); -int auth_rhosts_rsa(struct passwd *, const char *, RSA *); +int auth_rhosts_rsa(struct passwd *, const char *, Key *); int auth_password(Authctxt *, const char *); int auth_rsa(struct passwd *, BIGNUM *); -int auth_rsa_read_key(char **, u_int *, BIGNUM *, BIGNUM *); int auth_rsa_challenge_dialog(RSA *); #ifdef KRB4 @@ -130,6 +130,7 @@ void userauth_finish(Authctxt *, int, char *); int auth_root_allowed(char *); int auth2_challenge(Authctxt *, char *); +void auth2_challenge_stop(Authctxt *); int allowed_user(struct passwd *); diff --git a/openssh/auth1.c b/openssh/auth1.c index 1fbfad9..c2d9989 100644 --- a/openssh/auth1.c +++ b/openssh/auth1.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth1.c,v 1.25 2001/06/26 16:15:23 dugsong Exp $"); +RCSID("$OpenBSD: auth1.c,v 1.35 2002/02/03 17:53:25 markus Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -22,6 +22,7 @@ RCSID("$OpenBSD: auth1.c,v 1.25 2001/06/26 16:15:23 dugsong Exp $"); #include "servconf.h" #include "compat.h" #include "auth.h" +#include "channels.h" #include "session.h" #include "misc.h" #include "uidswap.h" @@ -66,18 +67,17 @@ 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; 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 && @@ -109,7 +109,7 @@ do_authloop(Authctxt *authctxt) info[0] = '\0'; /* Get a packet from the client. */ - type = packet_read(&plen); + type = packet_read(); /* Process the packet. */ switch (type) { @@ -120,17 +120,16 @@ do_authloop(Authctxt *authctxt) verbose("Kerberos authentication disabled."); } else { char *kdata = packet_get_string(&dlen); - - packet_integrity_check(plen, 4 + dlen, type); - + packet_check_eom(); + if (kdata[0] == 4) { /* KRB_PROT_VERSION */ #ifdef KRB4 KTEXT_ST tkt; - + 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), @@ -143,7 +142,7 @@ do_authloop(Authctxt *authctxt) krb5_data tkt; tkt.length = dlen; tkt.data = kdata; - + if (auth_krb5(authctxt, &tkt, &client_user)) { authenticated = 1; snprintf(info, sizeof(info), @@ -156,7 +155,7 @@ do_authloop(Authctxt *authctxt) } break; #endif /* KRB4 || KRB5 */ - + #if defined(AFS) || defined(KRB5) /* XXX - punt on backward compatibility here. */ case SSH_CMSG_HAVE_KERBEROS_TGT: @@ -168,7 +167,7 @@ do_authloop(Authctxt *authctxt) break; #endif /* AFS */ #endif /* AFS || KRB5 */ - + case SSH_CMSG_AUTH_RHOSTS: if (!options.rhosts_authentication) { verbose("Rhosts authentication disabled."); @@ -181,7 +180,7 @@ do_authloop(Authctxt *authctxt) * 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); @@ -202,24 +201,20 @@ do_authloop(Authctxt *authctxt) 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); + "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); - RSA_free(client_host_key); + authenticated = auth_rhosts_rsa(pw, client_user, + client_host_key); + key_free(client_host_key); snprintf(info, sizeof info, " ruser %.100s", client_user); break; @@ -230,9 +225,10 @@ do_authloop(Authctxt *authctxt) 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; @@ -248,7 +244,7 @@ do_authloop(Authctxt *authctxt) * 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 */ @@ -286,7 +282,7 @@ do_authloop(Authctxt *authctxt) 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); @@ -313,9 +309,9 @@ do_authloop(Authctxt *authctxt) #ifdef HAVE_CYGWIN if (authenticated && - !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) { + !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) { packet_disconnect("Authentication rejected for uid %d.", - (int)pw->pw_uid); + pw == NULL ? -1 : pw->pw_uid); authenticated = 0; } #else @@ -343,7 +339,7 @@ do_authloop(Authctxt *authctxt) if (authctxt->failures++ > AUTH_FAIL_MAX) { #ifdef WITH_AIXAUTHENTICATE loginfailed(authctxt->user, - get_canonical_hostname(options.reverse_mapping_check), + get_canonical_hostname(options.verify_reverse_mapping), "ssh"); #endif /* WITH_AIXAUTHENTICATE */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); @@ -360,20 +356,19 @@ do_authloop(Authctxt *authctxt) * been exchanged and encryption is enabled. */ void -do_authentication() +do_authentication(void) { Authctxt *authctxt; struct passwd *pw; - int plen; u_int ulen; char *p, *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'; @@ -381,7 +376,7 @@ do_authentication() /* XXX - SSH.com Kerberos v5 braindeath. */ if ((p = strchr(user, '@')) != NULL) *p = '\0'; - + authctxt = authctxt_new(); authctxt->user = user; authctxt->style = style; @@ -400,8 +395,7 @@ do_authentication() setproctitle("%s", pw ? user : "unknown"); #ifdef USE_PAM - if (pw) - start_pam(user); + start_pam(pw == NULL ? "NOUSER" : user); #endif /* diff --git a/openssh/auth2-chall.c b/openssh/auth2-chall.c index 5e6a691..9f1d932 100644 --- a/openssh/auth2-chall.c +++ b/openssh/auth2-chall.c @@ -23,10 +23,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: auth2-chall.c,v 1.8 2001/09/27 15:31:17 markus Exp $"); +RCSID("$OpenBSD: auth2-chall.c,v 1.16 2002/01/13 17:57:37 markus Exp $"); #include "ssh2.h" #include "auth.h" +#include "buffer.h" #include "packet.h" #include "xmalloc.h" #include "dispatch.h" @@ -35,7 +36,7 @@ RCSID("$OpenBSD: auth2-chall.c,v 1.8 2001/09/27 15:31:17 markus Exp $"); static int auth2_challenge_start(Authctxt *); static int send_userauth_info_request(Authctxt *); -static void input_userauth_info_response(int, int, void *); +static void input_userauth_info_response(int, u_int32_t, void *); #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; @@ -68,22 +69,25 @@ static KbdintAuthctxt * kbdint_alloc(const char *devs) { KbdintAuthctxt *kbdintctxt; + Buffer b; int i; - char buf[1024]; kbdintctxt = xmalloc(sizeof(KbdintAuthctxt)); if (strcmp(devs, "") == 0) { - buf[0] = '\0'; + buffer_init(&b); for (i = 0; devices[i]; i++) { - if (i != 0) - strlcat(buf, ",", sizeof(buf)); - strlcat(buf, devices[i]->name, sizeof(buf)); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, devices[i]->name, + strlen(devices[i]->name)); } - debug("kbdint_alloc: devices '%s'", buf); - kbdintctxt->devices = xstrdup(buf); + 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; @@ -151,11 +155,23 @@ auth2_challenge(Authctxt *authctxt, char *devs) if (authctxt->user == NULL || !devs) return 0; - if (authctxt->kbdintctxt == 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) @@ -166,21 +182,18 @@ auth2_challenge_start(Authctxt *authctxt) kbdintctxt->devices ? kbdintctxt->devices : ""); if (kbdint_next_device(kbdintctxt) == 0) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + 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) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); return 0; } if (send_userauth_info_request(authctxt) == 0) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); return 0; } dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, @@ -225,7 +238,7 @@ send_userauth_info_request(Authctxt *authctxt) } static void -input_userauth_info_response(int type, int plen, void *ctxt) +input_userauth_info_response(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; KbdintAuthctxt *kbdintctxt; @@ -248,7 +261,7 @@ input_userauth_info_response(int type, int plen, void *ctxt) for (i = 0; i < nresp; i++) response[i] = packet_get_string(NULL); } - packet_done(); + packet_check_eom(); if (authctxt->valid) { res = kbdintctxt->device->respond(kbdintctxt->ctxt, @@ -271,10 +284,8 @@ input_userauth_info_response(int type, int plen, void *ctxt) break; case 1: /* Authentication needs further interaction */ - authctxt->postponed = 1; - if (send_userauth_info_request(authctxt) == 0) { - authctxt->postponed = 0; - } + if (send_userauth_info_request(authctxt) == 1) + authctxt->postponed = 1; break; default: /* Failure! */ @@ -284,18 +295,12 @@ input_userauth_info_response(int type, int plen, void *ctxt) len = strlen("keyboard-interactive") + 2 + strlen(kbdintctxt->device->name); method = xmalloc(len); - method[0] = '\0'; - strlcat(method, "keyboard-interactive", len); - strlcat(method, "/", len); - strlcat(method, kbdintctxt->device->name, len); + snprintf(method, len, "keyboard-interactive/%s", + kbdintctxt->device->name); if (!authctxt->postponed) { - /* unregister callback */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); - if (authenticated) { - kbdint_free(kbdintctxt); - authctxt->kbdintctxt = NULL; + auth2_challenge_stop(authctxt); } else { /* start next device */ /* may set authctxt->postponed */ diff --git a/openssh/auth2-pam.c b/openssh/auth2-pam.c index b6eaf08..e442ca2 100644 --- a/openssh/auth2-pam.c +++ b/openssh/auth2-pam.c @@ -16,7 +16,7 @@ RCSID("$Id$"); 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, int plen, void *ctxt); +void input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt); struct { int finished, num_received, num_expected; @@ -128,7 +128,7 @@ do_pam_conversation_kbd_int(int num_msg, const struct pam_message **msg, } void -input_userauth_info_response_pam(int type, int plen, void *ctxt) +input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt) { Authctxt *authctxt = ctxt; unsigned int nresp = 0, rlen = 0, i = 0; @@ -152,7 +152,7 @@ input_userauth_info_response_pam(int type, int plen, void *ctxt) context_pam2.finished = 1; - packet_done(); + packet_check_eom(); } #endif diff --git a/openssh/auth2.c b/openssh/auth2.c index 1920eb3..f2a801e 100644 --- a/openssh/auth2.c +++ b/openssh/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.72 2001/11/07 22:41:51 markus Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $"); #include @@ -69,9 +69,8 @@ struct Authmethod { /* protocol */ -static void input_service_request(int, int, void *); -static void input_userauth_request(int, int, void *); -static void protocol_error(int, int, void *); +static void input_service_request(int, u_int32_t, void *); +static void input_userauth_request(int, u_int32_t, void *); /* helper */ static Authmethod *authmethod_lookup(const char *); @@ -111,7 +110,7 @@ Authmethod authmethods[] = { */ void -do_authentication2() +do_authentication2(void) { Authctxt *authctxt = authctxt_new(); @@ -123,30 +122,20 @@ do_authentication2() if (options.pam_authentication_via_kbd_int) options.kbd_interactive_authentication = 1; - 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); } static 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(); -} - -static void -input_service_request(int type, int plen, void *ctxt) +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"); @@ -173,7 +162,7 @@ input_service_request(int type, int plen, void *ctxt) } static void -input_userauth_request(int type, int plen, void *ctxt) +input_userauth_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Authmethod *m = NULL; @@ -220,14 +209,8 @@ input_userauth_request(int type, int plen, void *ctxt) authctxt->user, authctxt->service, user, service); } /* 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); @@ -271,7 +254,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) /* 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(); @@ -281,7 +264,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) if (authctxt->failures++ > AUTH_FAIL_MAX) { #ifdef WITH_AIXAUTHENTICATE loginfailed(authctxt->user, - get_canonical_hostname(options.reverse_mapping_check), + get_canonical_hostname(options.verify_reverse_mapping), "ssh"); #endif /* WITH_AIXAUTHENTICATE */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); @@ -334,14 +317,14 @@ userauth_none(Authctxt *authctxt) Authmethod *m = authmethod_lookup("none"); if (m != NULL) m->enabled = NULL; - packet_done(); + packet_check_eom(); userauth_banner(); if (authctxt->valid == 0) return(0); #ifdef HAVE_CYGWIN - if (check_nt_auth(1, authctxt->pw->pw_uid) == 0) + if (check_nt_auth(1, authctxt->pw) == 0) return(0); #endif #ifdef USE_PAM @@ -364,10 +347,10 @@ userauth_passwd(Authctxt *authctxt) if (change) log("password change not supported"); password = packet_get_string(&len); - packet_done(); + packet_check_eom(); if (authctxt->valid && #ifdef HAVE_CYGWIN - check_nt_auth(1, authctxt->pw->pw_uid) && + check_nt_auth(1, authctxt->pw) && #endif #ifdef USE_PAM auth_pam_password(authctxt->pw, password) == 1) @@ -390,7 +373,7 @@ userauth_kbdint(Authctxt *authctxt) lang = packet_get_string(NULL); devs = packet_get_string(NULL); - packet_done(); + packet_check_eom(); debug("keyboard-interactive devs %s", devs); @@ -404,7 +387,7 @@ userauth_kbdint(Authctxt *authctxt) xfree(devs); xfree(lang); #ifdef HAVE_CYGWIN - if (check_nt_auth(0, authctxt->pw->pw_uid) == 0) + if (check_nt_auth(0, authctxt->pw) == 0) return(0); #endif return authenticated; @@ -414,8 +397,9 @@ static int userauth_pubkey(Authctxt *authctxt) { Buffer b; - Key *key; - char *pkalg, *pkblob, *sig; + Key *key = NULL; + char *pkalg; + u_char *pkblob, *sig; u_int alen, blen, slen; int have_sig, pktype; int authenticated = 0; @@ -441,76 +425,84 @@ userauth_pubkey(Authctxt *authctxt) 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; + log("userauth_pubkey: unsupported public key algorithm: %s", + pkalg); + goto done; } 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); + 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); + 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; - } + /* 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_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 (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); } + 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->pw_uid) == 0) + if (check_nt_auth(0, authctxt->pw) == 0) return(0); #endif return authenticated; @@ -520,8 +512,9 @@ static int userauth_hostbased(Authctxt *authctxt) { Buffer b; - Key *key; - char *pkalg, *pkblob, *sig, *cuser, *chost, *service; + Key *key = NULL; + char *pkalg, *cuser, *chost, *service; + u_char *pkblob, *sig; u_int alen, blen, slen; int pktype; int authenticated = 0; @@ -554,7 +547,12 @@ userauth_hostbased(Authctxt *authctxt) } key = key_from_blob(pkblob, blen); if (key == NULL) { - debug("userauth_hostbased: cannot decode key: %s", pkalg); + 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" : @@ -579,10 +577,10 @@ userauth_hostbased(Authctxt *authctxt) authenticated = 1; buffer_clear(&b); - key_free(key); - done: debug2("userauth_hostbased: authenticated %d", authenticated); + if (key != NULL) + key_free(key); xfree(pkalg); xfree(pkblob); xfree(cuser); @@ -605,31 +603,22 @@ static char * authmethods_get(void) { Authmethod *method = NULL; - u_int size = 0; + Buffer b; char *list; + buffer_init(&b); 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) - continue; - if (method->enabled != NULL && *(method->enabled) != 0) { - if (list[0] != '\0') - strlcat(list, DELIM, size); - strlcat(list, method->name, size); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, method->name, strlen(method->name)); } } + buffer_append(&b, "\0", 1); + list = xstrdup(buffer_ptr(&b)); + buffer_free(&b); return list; } @@ -657,6 +646,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) u_long linenum = 0; struct stat st; Key *found; + char *fp; if (pw == NULL) return 0; @@ -724,6 +714,10 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) 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; } } @@ -761,9 +755,10 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, Key *key) { const char *resolvedname, *ipaddr, *lookup; - int host_status, len; + HostStatus host_status; + int len; - resolvedname = get_canonical_hostname(options.reverse_mapping_check); + resolvedname = get_canonical_hostname(options.verify_reverse_mapping); ipaddr = get_remote_ipaddr(); debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", @@ -801,4 +796,3 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, return (host_status == HOST_OK); } - diff --git a/openssh/authfd.c b/openssh/authfd.c index d6366ee..fa76435 100644 --- a/openssh/authfd.c +++ b/openssh/authfd.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfd.c,v 1.45 2001/09/19 19:35:30 stevesk Exp $"); +RCSID("$OpenBSD: authfd.c,v 1.48 2002/02/24 19:14:59 markus Exp $"); #include @@ -217,7 +217,7 @@ ssh_get_num_identities(AuthenticationConnection *auth, int version) 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; @@ -286,7 +286,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio * 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); @@ -344,7 +344,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, 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) { @@ -374,8 +374,8 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, 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; @@ -438,7 +438,7 @@ 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); diff --git a/openssh/authfd.h b/openssh/authfd.h index 8075a7e..0f2ca7a 100644 --- a/openssh/authfd.h +++ b/openssh/authfd.h @@ -1,3 +1,5 @@ +/* $OpenBSD: authfd.h,v 1.23 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". */ -/* RCSID("$OpenBSD: authfd.h,v 1.21 2001/08/07 10:37:46 markus Exp $"); */ - #ifndef AUTHFD_H #define AUTHFD_H @@ -74,7 +74,7 @@ ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], u_int, u_char[16]); int -ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, int *, u_char *, - int); +ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *, + u_int); #endif /* AUTHFD_H */ diff --git a/openssh/authfile.c b/openssh/authfile.c index 135be76..de8b102 100644 --- a/openssh/authfile.c +++ b/openssh/authfile.c @@ -36,7 +36,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfile.c,v 1.39 2001/10/07 10:29:52 markus Exp $"); +RCSID("$OpenBSD: authfile.c,v 1.48 2002/02/28 15:46:33 markus Exp $"); #include #include @@ -50,6 +50,7 @@ RCSID("$OpenBSD: authfile.c,v 1.39 2001/10/07 10:29:52 markus Exp $"); #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[] = @@ -67,8 +68,8 @@ 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; @@ -77,11 +78,9 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, * 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. */ @@ -118,7 +117,7 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, 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. */ @@ -128,11 +127,13 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, 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. */ @@ -147,7 +148,7 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase, 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); @@ -167,8 +168,8 @@ key_save_private_pem(Key *key, const char *filename, const char *_passphrase, 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); @@ -239,7 +240,7 @@ key_load_public_rsa1(int fd, const char *filename, char **commentp) 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, @@ -313,18 +314,16 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase, 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, @@ -378,12 +377,14 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase, } /* 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); @@ -406,17 +407,7 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase, 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); @@ -450,7 +441,7 @@ key_load_private_pem(int fd, int type, const char *passphrase, 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; @@ -459,7 +450,7 @@ key_load_private_pem(int fd, int type, const char *passphrase, 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; @@ -586,7 +577,7 @@ key_try_load_public(Key *k, const char *filename, char **commentp) while (fgets(line, sizeof(line), f)) { line[sizeof(line)-1] = '\0'; cp = line; - switch(*cp){ + switch (*cp) { case '#': case '\n': case '\0': diff --git a/openssh/authfile.h b/openssh/authfile.h index c8b31fb..c614ca1 100644 --- a/openssh/authfile.h +++ b/openssh/authfile.h @@ -1,3 +1,5 @@ +/* $OpenBSD: authfile.h,v 1.9 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,8 +12,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* $OpenBSD: authfile.h,v 1.8 2001/06/26 17:27:22 markus Exp $ */ - #ifndef AUTHFILE_H #define AUTHFILE_H diff --git a/openssh/bufaux.c b/openssh/bufaux.c index b17256d..23bc0c8 100644 --- a/openssh/bufaux.c +++ b/openssh/bufaux.c @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: bufaux.c,v 1.17 2001/01/21 19:05:45 markus Exp $"); +RCSID("$OpenBSD: bufaux.c,v 1.22 2002/01/18 18:14:17 stevesk Exp $"); #include #include "bufaux.h" @@ -62,7 +62,7 @@ buffer_put_bignum(Buffer *buffer, BIGNUM *value) 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); @@ -77,7 +77,7 @@ buffer_put_bignum(Buffer *buffer, BIGNUM *value) /* * Retrieves an BIGNUM from the buffer. */ -int +void buffer_get_bignum(Buffer *buffer, BIGNUM *value) { int bits, bytes; @@ -90,11 +90,9 @@ buffer_get_bignum(Buffer *buffer, BIGNUM *value) bytes = (bits + 7) / 8; 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; } /* @@ -112,16 +110,16 @@ buffer_put_bignum2(Buffer *buffer, BIGNUM *value) 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]; } } @@ -130,15 +128,14 @@ buffer_put_bignum2(Buffer *buffer, BIGNUM *value) xfree(buf); } -int +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_char *bin = buffer_get_string(buffer, (u_int *)&len); BN_bin2bn(bin, len, value); xfree(bin); - return len; } /* @@ -191,11 +188,11 @@ buffer_put_int64(Buffer *buffer, u_int64_t value) * 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_int len; - char *value; + u_char *value; /* Get the length. */ len = buffer_get_int(buffer); if (len > 256 * 1024) diff --git a/openssh/bufaux.h b/openssh/bufaux.h index d1af098..4000134 100644 --- a/openssh/bufaux.h +++ b/openssh/bufaux.h @@ -1,3 +1,5 @@ +/* $OpenBSD: bufaux.h,v 1.16 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,8 +12,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: bufaux.h,v 1.13 2001/06/26 17:27:22 markus Exp $"); */ - #ifndef BUFAUX_H #define BUFAUX_H @@ -20,11 +20,10 @@ void buffer_put_bignum(Buffer *, BIGNUM *); void buffer_put_bignum2(Buffer *, BIGNUM *); +void buffer_get_bignum(Buffer *, BIGNUM *); +void buffer_get_bignum2(Buffer *, BIGNUM *); -int buffer_get_bignum(Buffer *, BIGNUM *); -int buffer_get_bignum2(Buffer *, BIGNUM *); - -u_int buffer_get_int(Buffer *); +u_int buffer_get_int(Buffer *); void buffer_put_int(Buffer *, u_int); #ifdef HAVE_U_INT64_T @@ -33,11 +32,9 @@ void buffer_put_int64(Buffer *, u_int64_t); #endif int buffer_get_char(Buffer *); - void buffer_put_char(Buffer *, int); -char *buffer_get_string(Buffer *, u_int *); - +void *buffer_get_string(Buffer *, u_int *); void buffer_put_string(Buffer *, const void *, u_int); void buffer_put_cstring(Buffer *, const char *); diff --git a/openssh/buffer.c b/openssh/buffer.c index 044caaf..40572e5 100644 --- a/openssh/buffer.c +++ b/openssh/buffer.c @@ -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.15 2002/01/18 18:14:17 stevesk Exp $"); #include "xmalloc.h" #include "buffer.h" @@ -53,11 +53,11 @@ buffer_clear(Buffer *buffer) /* 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,11 @@ buffer_append(Buffer *buffer, const char *data, u_int len) * 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 the buffer is empty, start using it from the beginning. */ if (buffer->offset == buffer->end) { buffer->offset = 0; @@ -77,9 +79,9 @@ buffer_append_space(Buffer *buffer, char **datap, u_int len) 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 @@ -96,6 +98,7 @@ restart: buffer->alloc += len + 32768; buffer->buf = xrealloc(buffer->buf, buffer->alloc); goto restart; + /* NOTREACHED */ } /* Returns the number of bytes of data in the buffer. */ @@ -109,7 +112,7 @@ buffer_len(Buffer *buffer) /* 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 +143,7 @@ buffer_consume_end(Buffer *buffer, u_int bytes) /* Returns a pointer to the first used byte in the buffer. */ -char * +void * buffer_ptr(Buffer *buffer) { return buffer->buf + buffer->offset; @@ -152,7 +155,7 @@ void 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]); diff --git a/openssh/buffer.h b/openssh/buffer.h index 845bfb6..5e4c412 100644 --- a/openssh/buffer.h +++ b/openssh/buffer.h @@ -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,13 +13,11 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: buffer.h,v 1.9 2001/06/26 17:27:23 markus Exp $"); */ - #ifndef BUFFER_H #define BUFFER_H typedef struct { - char *buf; /* Buffer for 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. */ @@ -28,12 +28,12 @@ void buffer_clear(Buffer *); void buffer_free(Buffer *); u_int buffer_len(Buffer *); -char *buffer_ptr(Buffer *); +void *buffer_ptr(Buffer *); -void buffer_append(Buffer *, const char *, u_int); -void buffer_append_space(Buffer *, char **, u_int); +void buffer_append(Buffer *, const void *, u_int); +void *buffer_append_space(Buffer *, u_int); -void buffer_get(Buffer *, char *, u_int); +void buffer_get(Buffer *, void *, u_int); void buffer_consume(Buffer *, u_int); void buffer_consume_end(Buffer *, u_int); diff --git a/openssh/canohost.c b/openssh/canohost.c index 6e6a045..03005aa 100644 --- a/openssh/canohost.c +++ b/openssh/canohost.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: canohost.c,v 1.27 2001/06/23 15:12:17 itojun Exp $"); +RCSID("$OpenBSD: canohost.c,v 1.31 2002/02/27 21:23:13 stevesk Exp $"); #include "packet.h" #include "xmalloc.h" @@ -27,7 +27,7 @@ static void check_ip_options(int, char *); */ static char * -get_remote_hostname(int socket, int reverse_mapping_check) +get_remote_hostname(int socket, int verify_reverse_mapping) { struct sockaddr_storage from; int i; @@ -68,13 +68,13 @@ get_remote_hostname(int socket, int reverse_mapping_check) check_ip_options(socket, ntop); 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"); 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); @@ -90,7 +90,7 @@ get_remote_hostname(int socket, int reverse_mapping_check) 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 @@ -154,7 +154,7 @@ check_ip_options(int socket, char *ipaddr) 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++) @@ -174,14 +174,14 @@ check_ip_options(int socket, char *ipaddr) */ 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; @@ -190,11 +190,11 @@ get_canonical_hostname(int reverse_mapping_check) /* 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; } @@ -230,7 +230,7 @@ get_socket_address(int socket, int remote, int flags) } /* 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; } @@ -261,7 +261,7 @@ get_local_name(int socket) */ const char * -get_remote_ipaddr() +get_remote_ipaddr(void) { static char *canonical_host_ip = NULL; @@ -281,11 +281,11 @@ get_remote_ipaddr() } 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; @@ -316,7 +316,7 @@ get_sock_port(int sock, int local) } /* 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); } @@ -344,13 +344,13 @@ get_peer_port(int sock) } int -get_remote_port() +get_remote_port(void) { return get_port(0); } int -get_local_port() +get_local_port(void) { return get_port(1); } diff --git a/openssh/channels.c b/openssh/channels.c index 62fd73d..2b1f33f 100644 --- a/openssh/channels.c +++ b/openssh/channels.c @@ -13,7 +13,7 @@ * called by a name other than "ssh" or "Secure Shell". * * SSH2 support added by Markus Friedl. - * Copyright (c) 1999, 2000, 2001 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. * @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.140 2001/10/10 22:18:47 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -54,6 +54,7 @@ RCSID("$OpenBSD: channels.c,v 1.140 2001/10/10 22:18:47 markus Exp $"); #include "canohost.h" #include "key.h" #include "authfd.h" +#include "pathnames.h" /* -- channel core */ @@ -145,7 +146,7 @@ channel_lookup(int id) { Channel *c; - if (id < 0 || id > channels_alloc) { + if (id < 0 || id >= channels_alloc) { log("channel_lookup: %d: bad id", id); return NULL; } @@ -216,7 +217,6 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, /* Do initial allocation if this is the first call. */ if (channels_alloc == 0) { - chan_init(); channels_alloc = 10; channels = xmalloc(channels_alloc * sizeof(Channel *)); for (i = 0; i < channels_alloc; i++) @@ -245,7 +245,9 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, 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; @@ -258,11 +260,10 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, 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->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 c; @@ -361,7 +362,7 @@ channel_free_all(void) */ void -channel_close_all() +channel_close_all(void) { int i; @@ -402,7 +403,7 @@ channel_stop_listening(void) */ int -channel_not_very_much_buffered_data() +channel_not_very_much_buffered_data(void) { u_int i; Channel *c; @@ -432,7 +433,7 @@ channel_not_very_much_buffered_data() /* Returns true if any channel is still open. */ int -channel_still_open() +channel_still_open(void) { int i; Channel *c; @@ -475,7 +476,7 @@ channel_still_open() /* Returns the id of an open channel suitable for keepaliving */ int -channel_find_open() +channel_find_open(void) { int i; Channel *c; @@ -520,7 +521,7 @@ channel_find_open() */ char * -channel_open_message() +channel_open_message(void) { Buffer buffer; Channel *c; @@ -587,36 +588,28 @@ channel_send_open(int id) } void -channel_request(int id, char *service, int wantconfirm) +channel_request_start(int local_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); + Channel *c = channel_lookup(local_id); if (c == NULL) { - log("channel_request: %d: bad id", id); + 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_callback(int id, int mtype, channel_callback_fn *fn, void *arg) +channel_register_confirm(int id, channel_callback_fn *fn) { Channel *c = channel_lookup(id); if (c == NULL) { - log("channel_register_callback: %d: bad id", id); + log("channel_register_comfirm: %d: bad id", id); return; } - c->cb_event = mtype; - c->cb_fn = fn; - c->cb_arg = arg; + c->confirm = fn; } void channel_register_cleanup(int id, channel_callback_fn *fn) @@ -651,15 +644,14 @@ channel_register_filter(int id, channel_filter_fn *fn) void channel_set_fds(int id, int rfd, int wfd, int efd, - int extusage, int nonblock) + 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; - /* XXX window size? */ - c->local_window = c->local_window_max = c->local_maxpacket * 2; + 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); @@ -701,28 +693,13 @@ channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset) } static void -channel_pre_open_15(Channel *c, fd_set * readset, fd_set * writeset) +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(); -static 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) { @@ -733,7 +710,7 @@ channel_pre_open_20(Channel *c, fd_set * readset, fd_set * writeset) } } /** 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); @@ -784,7 +761,7 @@ x11_open_helper(Buffer *b) return 0; /* Parse the lengths of variable-length fields. */ - ucp = (u_char *) buffer_ptr(b); + 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]; @@ -793,7 +770,7 @@ x11_open_helper(Buffer *b) 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; } @@ -865,14 +842,19 @@ channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset) 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); } } @@ -883,7 +865,7 @@ 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; @@ -930,7 +912,7 @@ channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset) 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); @@ -1002,10 +984,16 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) 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", @@ -1015,17 +1003,12 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(buf), 1); - if (nc == NULL) { - close(newsock); - xfree(remote_ipaddr); - return; - } if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring("x11"); packet_put_int(nc->self); - packet_put_int(c->local_window_max); - packet_put_int(c->local_maxpacket); + 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) { @@ -1133,15 +1116,11 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) error("accept: %.100s", strerror(errno)); return; } + set_nodelay(newsock); nc = channel_new(rtype, nextstate, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(rtype), 1); - if (nc == NULL) { - error("channel_post_port_listener: no new channel:"); - close(newsock); - return; - } nc->listening_port = c->listening_port; nc->host_port = c->host_port; strlcpy(nc->path, c->path, sizeof(nc->path)); @@ -1184,11 +1163,6 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, name, 1); - if (nc == NULL) { - error("channel_post_auth_listener: channel_new failed"); - xfree(name); - close(newsock); - } if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring("auth-agent@openssh.com"); @@ -1210,8 +1184,7 @@ channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset) socklen_t sz = sizeof(err); if (FD_ISSET(c->sock, writeset)) { - if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, (char *)&err, - &sz) < 0) { + if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { err = errno; error("getsockopt SO_ERROR failed"); } @@ -1269,7 +1242,7 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) 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: input draining.", c->self); } else { @@ -1277,7 +1250,7 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) } 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); @@ -1311,7 +1284,7 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) chan_mark_dead(c); return -1; } else if (compat13) { - buffer_consume(&c->output, buffer_len(&c->output)); + buffer_clear(&c->output); debug("channel %d: input draining.", c->self); c->type = SSH_CHANNEL_INPUT_DRAINING; } else { @@ -1368,7 +1341,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) 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) { @@ -1403,23 +1376,15 @@ channel_check_window(Channel *c) } static void -channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset) +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); -} - -static void -channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset) -{ - if (c->delayed) + if (!compat20) return; - channel_handle_rfd(c, readset, writeset); - channel_handle_wfd(c, readset, writeset); channel_handle_efd(c, readset, writeset); - channel_check_window(c); } @@ -1432,7 +1397,7 @@ channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset) 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); } @@ -1441,7 +1406,7 @@ channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset) 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; @@ -1450,13 +1415,13 @@ channel_handler_init_20(void) 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; } static void @@ -1472,19 +1437,19 @@ channel_handler_init_13(void) 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; } 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; @@ -1495,16 +1460,16 @@ channel_handler_init_15(void) 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; } 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; } @@ -1601,7 +1566,7 @@ channel_after_select(fd_set * readset, fd_set * 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; @@ -1699,7 +1664,7 @@ channel_output_poll() /* -- 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; @@ -1723,9 +1688,8 @@ channel_input_data(int type, int plen, void *ctxt) /* 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); @@ -1737,15 +1701,14 @@ channel_input_data(int type, int plen, void *ctxt) 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; @@ -1771,7 +1734,7 @@ channel_input_extended_data(int type, int plen, void *ctxt) 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); @@ -1785,36 +1748,36 @@ channel_input_extended_data(int type, int plen, void *ctxt) } 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) { + 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); @@ -1839,30 +1802,31 @@ channel_input_close(int type, int plen, void *ctxt) * 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); @@ -1873,14 +1837,11 @@ channel_input_close_confirmation(int type, int plen, void *ctxt) } 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); @@ -1895,21 +1856,21 @@ channel_input_open_confirmation(int type, int plen, void *ctxt) 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, c->remote_window, c->remote_maxpacket); } + packet_check_eom(); } static char * reason2txt(int reason) { - switch(reason) { + switch (reason) { case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED: return "administratively prohibited"; case SSH2_OPEN_CONNECT_FAILED: @@ -1923,15 +1884,12 @@ reason2txt(int 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); @@ -1944,7 +1902,6 @@ channel_input_open_failure(int type, int plen, void *ctxt) msg = packet_get_string(NULL); lang = packet_get_string(NULL); } - packet_done(); log("channel %d: open failed: %s%s%s", id, reason2txt(reason), msg ? ": ": "", msg ? msg : ""); if (msg != NULL) @@ -1952,37 +1909,13 @@ channel_input_open_failure(int type, int plen, void *ctxt) if (lang != NULL) xfree(lang); } + packet_check_eom(); /* Free the channel. This will also close the socket. */ channel_free(c); } 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); - } -} - -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; @@ -2000,13 +1933,13 @@ channel_input_window_adjust(int type, int plen, void *ctxt) return; } adjust = packet_get_int(); - packet_done(); + packet_check_eom(); debug2("channel %d: rcvd adjust %d", id, adjust); c->remote_window += adjust; } void -channel_input_port_open(int type, int plen, void *ctxt) +channel_input_port_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; u_short host_port; @@ -2022,18 +1955,13 @@ channel_input_port_open(int type, int plen, void *ctxt) } else { originator_string = xstrdup("unknown (remote did not supply name)"); } - packet_done(); + 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); - if (c == NULL) { - error("channel_input_port_open: channel_new failed"); - close(sock); - } else { - c->remote_id = remote_id; - } + c->remote_id = remote_id; } if (c == NULL) { packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); @@ -2052,53 +1980,30 @@ channel_set_af(int af) IPv4or6 = af; } -/* - * 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) -{ - return channel_request_forwarding( - NULL, listen_port, - host_to_connect, port_to_connect, - gateway_ports, /*remote_fwd*/ 0); -} - -/* - * 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) { Channel *c; - int success, sock, on = 1, type; + 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; - type = SSH_CHANNEL_RPORT_LISTENER; - } else { - host = host_to_connect; - type = SSH_CHANNEL_PORT_LISTENER; + if (host == NULL) { + error("No forward host name."); + return success; } - 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 @@ -2116,7 +2021,7 @@ channel_request_forwarding( 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. */ @@ -2130,10 +2035,10 @@ channel_request_forwarding( * 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. */ @@ -2157,23 +2062,36 @@ channel_request_forwarding( c = channel_new("port listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("port listener"), 1); - if (c == NULL) { - error("channel_request_forwarding: channel_new failed"); - close(sock); - continue; - } 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. @@ -2183,7 +2101,7 @@ void 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) @@ -2210,7 +2128,7 @@ channel_request_remote_forwarding(u_short listen_port, 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; @@ -2259,7 +2177,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports) 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); @@ -2271,7 +2189,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports) * 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; @@ -2352,6 +2270,7 @@ connect_to(const char *host, u_short port) return -1; } /* success */ + set_nodelay(sock); return sock; } @@ -2396,32 +2315,32 @@ channel_connect_to(const char *host, u_short port) /* * 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 a suitable display number for the DISPLAY variable, or -1 if + * an error occurs. */ -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) { + 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) @@ -2430,7 +2349,7 @@ x11_create_display_inet(int screen_number, int x11_display_offset) if (sock < 0) { if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) { error("socket: %.100s", strerror(errno)); - return NULL; + return -1; } else { debug("x11_create_display_inet: Socket family %d not supported", ai->ai_family); @@ -2439,14 +2358,12 @@ x11_create_display_inet(int screen_number, int x11_display_offset) } 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; @@ -2466,103 +2383,47 @@ x11_create_display_inet(int screen_number, int x11_display_offset) } 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; - } - } - - /* Set up a suitable value for the DISPLAY variable. */ - if (gethostname(hostname, sizeof(hostname)) < 0) - fatal("gethostname: %.100s", strerror(errno)); - -#ifdef IPADDR_IN_DISPLAY - /* - * HPUX detects the local hostname in the DISPLAY variable and tries - * to set up a shared memory connection to the server, which it - * incorrectly supposes to be local. - * - * The workaround - as used in later $$H and other programs - is - * is to set display to the host's IP address. - */ - { - struct hostent *he; - struct in_addr my_addr; - - he = gethostbyname(hostname); - if (he == NULL) { - error("[X11-broken-fwd-hostname-workaround] Could not get " - "IP address for hostname %s.", hostname); - - packet_send_debug("[X11-broken-fwd-hostname-workaround]" - "Could not get IP address for hostname %s.", hostname); - - shutdown(sock, SHUT_RDWR); - close(sock); - - return NULL; + return -1; } - - memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr)); - - /* Set DISPLAY to :screen.display */ - snprintf(display, sizeof(display), "%.50s:%d.%d", inet_ntoa(my_addr), - display_number, screen_number); } -#else /* IPADDR_IN_DISPLAY */ - /* Just set DISPLAY to hostname:screen.display */ - snprintf(display, sizeof display, "%.400s:%d.%d", hostname, - display_number, screen_number); -#endif /* IPADDR_IN_DISPLAY */ /* 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. */ + return display_number; } -#ifndef X_UNIX_PATH -#define X_UNIX_PATH "/tmp/.X11-unix/X" -#endif - 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; } @@ -2597,7 +2458,7 @@ x11_connect_display(void) /* 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. */ @@ -2612,8 +2473,7 @@ x11_connect_display(void) * 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); @@ -2623,7 +2483,7 @@ x11_connect_display(void) /* 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; } @@ -2659,6 +2519,7 @@ x11_connect_display(void) strerror(errno)); return -1; } + set_nodelay(sock); return sock; } @@ -2669,7 +2530,7 @@ x11_connect_display(void) */ void -x11_input_open(int type, int plen, void *ctxt) +x11_input_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; int remote_id, sock = 0; @@ -2684,7 +2545,7 @@ x11_input_open(int type, int plen, void *ctxt) } else { remote_host = xstrdup("unknown (remote did not supply name)"); } - packet_done(); + packet_check_eom(); /* Obtain a connection to the real X display. */ sock = x11_connect_display(); @@ -2693,13 +2554,8 @@ x11_input_open(int type, int plen, void *ctxt) c = channel_new("connected x11 socket", SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0, remote_host, 1); - if (c == NULL) { - error("x11_input_open: channel_new failed"); - close(sock); - } else { - c->remote_id = remote_id; - c->force_drain = 1; - } + c->remote_id = remote_id; + c->force_drain = 1; } if (c == NULL) { /* Send refusal to the remote host. */ @@ -2716,10 +2572,10 @@ x11_input_open(int type, int plen, void *ctxt) /* 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; @@ -2727,7 +2583,7 @@ deny_input_open(int type, int plen, void *ctxt) 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."); @@ -2811,7 +2667,7 @@ x11_request_forwarding_with_spoofing(int client_session_id, /* 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(); @@ -2825,7 +2681,7 @@ auth_request_forwarding() */ char * -auth_get_socket_name() +auth_get_socket_name(void) { return auth_sock_name; } @@ -2896,8 +2752,7 @@ auth_input_request_forwarding(struct passwd * pw) /* Bind it to the name. */ memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, auth_sock_name, - sizeof(sunaddr.sun_path)); + 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)); @@ -2914,13 +2769,6 @@ auth_input_request_forwarding(struct passwd * pw) SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, xstrdup("auth socket"), 1); - if (nc == NULL) { - error("auth_input_request_forwarding: channel_new failed"); - auth_sock_cleanup_proc(pw); - fatal_remove_cleanup(auth_sock_cleanup_proc, pw); - close(sock); - return 0; - } strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); return 1; } @@ -2928,16 +2776,15 @@ 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) +auth_input_open_request(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; int remote_id, sock; char *name; - packet_integrity_check(plen, 4, type); - /* Read the remote channel number from the message. */ remote_id = packet_get_int(); + packet_check_eom(); /* * Get a connection to the local authentication agent (this may again @@ -2955,14 +2802,8 @@ auth_input_open_request(int type, int plen, void *ctxt) name = xstrdup("authentication agent connection"); c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, -1, 0, 0, 0, name, 1); - if (c == NULL) { - error("auth_input_open_request: channel_new failed"); - xfree(name); - close(sock); - } else { - c->remote_id = remote_id; - c->force_drain = 1; - } + c->remote_id = remote_id; + c->force_drain = 1; } if (c == NULL) { packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); diff --git a/openssh/channels.h b/openssh/channels.h index 11ebb7b..707d9a9 100644 --- a/openssh/channels.h +++ b/openssh/channels.h @@ -1,3 +1,5 @@ +/* $OpenBSD: channels.h,v 1.65 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,7 +12,7 @@ * called by a name other than "ssh" or "Secure Shell". */ /* - * Copyright (c) 1999, 2000, 2001 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,7 +34,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("$OpenBSD: channels.h,v 1.51 2001/11/07 22:53:21 markus Exp $"); */ #ifndef CHANNEL_H #define CHANNEL_H @@ -68,8 +69,8 @@ struct Channel { int type; /* channel type/state */ int self; /* my own channel identifier */ int remote_id; /* channel identifier for remote peer */ - 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 */ @@ -96,13 +97,12 @@ struct Channel { int local_consumed; 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 *confirm; channel_callback_fn *detach_user; /* filter */ @@ -114,24 +114,24 @@ struct Channel { #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) +#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 0x01 -#define CHAN_INPUT_WAIT_DRAIN 0x02 -#define CHAN_INPUT_WAIT_OCLOSE 0x04 -#define CHAN_INPUT_CLOSED 0x08 +#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 0x10 -#define CHAN_OUTPUT_WAIT_DRAIN 0x20 -#define CHAN_OUTPUT_WAIT_IEOF 0x40 -#define CHAN_OUTPUT_CLOSED 0x80 +#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 @@ -140,33 +140,31 @@ struct Channel { Channel *channel_lookup(int); Channel *channel_new(char *, int, int, int, int, int, int, int, char *, int); -void channel_set_fds(int, int, int, int, int, 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(int, char *, int); void channel_request_start(int, char *, int); -void channel_register_callback(int, int mtype, channel_callback_fn *, void *); 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_channel_request(int, int, void *); -void channel_input_close(int, int, void *); -void channel_input_close_confirmation(int, int, void *); -void channel_input_data(int, int, void *); -void channel_input_extended_data(int, int, void *); -void channel_input_ieof(int, int, void *); -void channel_input_oclose(int, int, void *); -void channel_input_open_confirmation(int, int, void *); -void channel_input_open_failure(int, int, void *); -void channel_input_port_open(int, int, void *); -void channel_input_window_adjust(int, int, void *); +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) */ @@ -189,20 +187,16 @@ 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_request_local_forwarding(u_short, const char *, u_short, int); -int -channel_request_forwarding(const char *, u_short, const char *, u_short, int, - int); +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); -char *x11_create_display(int); -char *x11_create_display_inet(int, int); -void x11_input_open(int, int, void *); -void x11_request_forwarding(void); +int x11_create_display_inet(int, int, 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, int, void *); +void deny_input_open(int, u_int32_t, void *); /* agent forwarding */ @@ -210,25 +204,21 @@ void auth_request_forwarding(void); char *auth_get_socket_name(void); void auth_sock_cleanup_proc(void *); int auth_input_request_forwarding(struct passwd *); -void auth_input_open_request(int, int, void *); +void auth_input_open_request(int, u_int32_t, void *); /* channel close */ int chan_is_dead(Channel *, int); void chan_mark_dead(Channel *); -void chan_init_iostates(Channel *); -void chan_init(void); -typedef void chan_event_fn(Channel *); +/* channel events */ -/* 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; +void chan_rcvd_oclose(Channel *); +void chan_read_failed(Channel *); +void chan_ibuf_empty(Channel *); -/* 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; +void chan_rcvd_ieof(Channel *); +void chan_write_failed(Channel *); +void chan_obuf_empty(Channel *); #endif diff --git a/openssh/cipher.c b/openssh/cipher.c index de25ff0..ce3f6f3 100644 --- a/openssh/cipher.c +++ b/openssh/cipher.c @@ -35,389 +35,60 @@ */ #include "includes.h" -RCSID("$OpenBSD: cipher.c,v 1.47 2001/08/23 11:31:59 markus Exp $"); +RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $"); #include "xmalloc.h" #include "log.h" #include "cipher.h" #include +#include "rijndael.h" + +static EVP_CIPHER *evp_ssh1_3des(void); +static EVP_CIPHER *evp_ssh1_bf(void); +static EVP_CIPHER *evp_rijndael(void); + +struct Cipher { + char *name; + int number; /* for ssh1 only */ + u_int block_size; + u_int key_len; + 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 }, + { "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 }, + + { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } +}; -/* no encryption */ -static void -none_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ -} -static void -none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ -} -static void -none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - memcpy(dest, src, len); -} - -/* DES */ -static 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); -} -static void -des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv)); -} -static 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); -} -static 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 */ -static 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); -} -static void -des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - memset(cc->u.des3.iv1, 0, sizeof(cc->u.des3.iv1)); - 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); -} -static 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); -} -static 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. - */ -static 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); -} -static void -des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - des_ncbc_encrypt(src, dest, len, cc->u.des3.key1, &cc->u.des3.iv1, - DES_ENCRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, &cc->u.des3.iv2, - DES_DECRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key3, &cc->u.des3.iv3, - DES_ENCRYPT); -} -static void -des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) -{ - des_ncbc_encrypt(src, dest, len, cc->u.des3.key3, &cc->u.des3.iv3, - DES_DECRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, &cc->u.des3.iv2, - DES_ENCRYPT); - des_ncbc_encrypt(dest, dest, len, cc->u.des3.key1, &cc->u.des3.iv1, - DES_DECRYPT); -} - -/* Blowfish */ -static void -blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - BF_set_key(&cc->u.bf.key, keylen, (u_char *)key); -} -static 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); -} -static 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); -} -static 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]; - } -} - -static 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); -} -static 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 */ -static void -arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - RC4_set_key(&cc->u.rc4, keylen, (u_char *)key); -} -static void -arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) -{ - RC4(&cc->u.rc4, len, (u_char *)src, dest); -} - -/* CAST */ -static void -cast_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - CAST_set_key(&cc->u.cast.key, keylen, (u_char *) key); -} -static 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); -} -static 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); -} -static void -cast_cbc_decrypt(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_DECRYPT); -} - -/* RIJNDAEL */ +/*--*/ -#define RIJNDAEL_BLOCKSIZE 16 -static void -rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen) -{ - rijndael_set_key(&cc->u.rijndael.enc, (char *)key, 8*keylen, 1); - rijndael_set_key(&cc->u.rijndael.dec, (char *)key, 8*keylen, 0); -} -static void -rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) -{ - if (iv == NULL || ivlen != RIJNDAEL_BLOCKSIZE) - fatal("bad/no IV for %s.", cc->cipher->name); - memcpy(cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE); -} -static void -rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) +u_int +cipher_blocksize(Cipher *c) { - rijndael_ctx *ctx = &cc->u.rijndael.enc; - u_char *iv = cc->u.rijndael.iv; - u_char in[RIJNDAEL_BLOCKSIZE]; - u_char *cprev, *cnow, *plain; - int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; - - if (len == 0) - return; - if (len % RIJNDAEL_BLOCKSIZE) - fatal("rijndael_cbc_encrypt: bad len %d", len); - cnow = dest; - plain = (u_char *) src; - cprev = iv; - for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, - cnow+=RIJNDAEL_BLOCKSIZE) { - for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) - in[j] = plain[j] ^ cprev[j]; - rijndael_encrypt(ctx, in, cnow); - cprev = cnow; - } - memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE); + return (c->block_size); } -static void -rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, - u_int len) +u_int +cipher_keylen(Cipher *c) { - rijndael_ctx *ctx = &cc->u.rijndael.dec; - u_char *iv = cc->u.rijndael.iv; - u_char ivsaved[RIJNDAEL_BLOCKSIZE]; - u_char *cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); - u_char *plain = dest+len-RIJNDAEL_BLOCKSIZE; - u_char *ivp; - int i, j, 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-=RIJNDAEL_BLOCKSIZE, - plain-=RIJNDAEL_BLOCKSIZE) { - rijndael_decrypt(ctx, cnow, plain); - ivp = (i == 1) ? iv : cnow-RIJNDAEL_BLOCKSIZE; - for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) - plain[j] ^= ivp[j]; - } - memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE); + return (c->key_len); } -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; @@ -457,7 +128,7 @@ ciphers_valid(const char *names) 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); @@ -496,8 +167,24 @@ cipher_name(int id) 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; + const EVP_CIPHER *type; + 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); @@ -505,24 +192,40 @@ cipher_init(CipherContext *cc, Cipher *cipher, 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); + 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); } 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); + if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0) + fatal("evp_crypt: EVP_Cipher failed"); } void -cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) +cipher_cleanup(CipherContext *cc) { - if (len % cc->cipher->block_size) - fatal("cipher_decrypt: bad ciphertext length %d", len); - cc->cipher->decrypt(cc, dest, src, len); + if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) + error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); } /* @@ -532,7 +235,7 @@ cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) void cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase) + const char *passphrase, int encrypt) { MD5_CTX md; u_char digest[16]; @@ -541,8 +244,257 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher, 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); + 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); + } + 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); + } + 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); + 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 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; + ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; + 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 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); +} + +/* 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 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; + rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_ALWAYS_CALL_INIT; + return (&rijndal_cbc); +} diff --git a/openssh/cipher.h b/openssh/cipher.h index 4533f5e..b3b0303 100644 --- a/openssh/cipher.h +++ b/openssh/cipher.h @@ -1,3 +1,5 @@ +/* $OpenBSD: cipher.h,v 1.32 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -32,16 +34,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: cipher.h,v 1.29 2001/08/23 11:31:59 markus 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. @@ -59,50 +55,18 @@ #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_key_schedule key3; - des_cblock iv1; - des_cblock iv2; - 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 { - u_char iv[16]; - 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); Cipher *cipher_by_name(const char *); @@ -111,9 +75,10 @@ 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); -void cipher_encrypt(CipherContext *, u_char *, const u_char *, u_int); -void cipher_decrypt(CipherContext *, u_char *, const u_char *, u_int); -void cipher_set_key_string(CipherContext *, Cipher *, const char *); - + 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 *); #endif /* CIPHER_H */ diff --git a/openssh/clientloop.c b/openssh/clientloop.c index cbcb1d1..65a6682 100644 --- a/openssh/clientloop.c +++ b/openssh/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.87 2001/11/09 18:59:23 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.96 2002/02/06 14:55:15 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -101,8 +101,8 @@ extern char *host; * 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 int received_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; @@ -254,7 +254,7 @@ client_make_packets_from_stdin_data(void) /* 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()) @@ -417,9 +417,9 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) /* 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. */ @@ -949,7 +949,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (received_signal) { if (in_non_blocking_mode) /* XXX */ leave_non_blocking(); - fatal("Killed by signal %d.", received_signal); + fatal("Killed by signal %d.", (int) received_signal); } /* @@ -994,11 +994,11 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* 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); @@ -1008,30 +1008,30 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /*********/ static void -client_input_stdout_data(int type, int plen, void *ctxt) +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); } static void -client_input_stderr_data(int type, int plen, void *ctxt) +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); } static void -client_input_exit_status(int type, int plen, void *ctxt) +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(); @@ -1057,7 +1057,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) 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); @@ -1072,10 +1072,6 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, xstrdup(originator_address), 1); - if (c == NULL) { - error("client_request_forwarded_tcpip: channel_new failed"); - close(sock); - } xfree(originator_address); xfree(listen_address); return c; @@ -1101,7 +1097,7 @@ client_request_x11(const char *request_type, int rchan) } 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); @@ -1113,10 +1109,6 @@ client_request_x11(const char *request_type, int rchan) SSH_CHANNEL_X11_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1); - if (c == NULL) { - error("client_request_x11: channel_new failed"); - close(sock); - } c->force_drain = 1; return c; } @@ -1139,17 +1131,13 @@ client_request_agent(const char *request_type, int rchan) SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, xstrdup("authentication agent connection"), 1); - if (c == NULL) { - error("client_request_agent: channel_new failed"); - close(sock); - } c->force_drain = 1; return c; } /* XXXX move to generic input handler */ static void -client_input_channel_open(int type, int plen, void *ctxt) +client_input_channel_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; char *ctype; @@ -1201,7 +1189,7 @@ client_input_channel_open(int type, int plen, void *ctxt) xfree(ctype); } static void -client_input_channel_req(int type, int plen, void *ctxt) +client_input_channel_req(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; int id, reply, success = 0; @@ -1226,7 +1214,7 @@ client_input_channel_req(int type, int plen, void *ctxt) } else if (strcmp(rtype, "exit-status") == 0) { success = 1; exit_status = packet_get_int(); - packet_done(); + packet_check_eom(); } if (reply) { packet_start(success ? @@ -1236,6 +1224,24 @@ client_input_channel_req(int type, int plen, void *ctxt) } xfree(rtype); } +static void +client_input_global_request(int type, u_int32_t seq, void *ctxt) +{ + char *rtype; + int want_reply; + int success = 0; + + 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) @@ -1250,6 +1256,7 @@ client_init_dispatch_20(void) 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); diff --git a/openssh/compat.c b/openssh/compat.c index 1d3e970..74d5ed8 100644 --- a/openssh/compat.c +++ b/openssh/compat.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2000, 2001 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,22 +23,14 @@ */ #include "includes.h" -RCSID("$OpenBSD: compat.c,v 1.53 2001/09/20 13:50:40 markus Exp $"); - -#ifdef HAVE_LIBPCRE -# include -#else /* Use native regex libraries */ -# ifdef HAVE_REGEX_H -# include -# else -# include "openbsd-compat/fake-regex.h" -# endif -#endif /* HAVE_LIBPCRE */ +RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 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; @@ -60,86 +52,97 @@ enable_compat13(void) 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| + { "OpenSSH-2.0*," + "OpenSSH-2.1*," + "OpenSSH_2.1*," + "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, - { "^OpenSSH_2\\.3\\.0", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| + { "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| + { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| SSH_BUG_NOREKEY}, - { "^OpenSSH_2\\.5\\.[01]p1", + { "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| + { "OpenSSH_2.5.0*," + "OpenSSH_2.5.1*," + "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, + { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY }, + { "Sun_SSH_1.0*", SSH_BUG_NOREKEY }, + { "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|SSH_BUG_OPENFAILURE| SSH_BUG_DUMMYCHAN }, - { "^2\\.0\\.1[1-2]", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| + { "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| + { "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\\.[23]\\.0", SSH_BUG_HMAC|SSH_BUG_DEBUG| + { "2.2.0*," + "2.3.0*", SSH_BUG_HMAC|SSH_BUG_DEBUG| SSH_BUG_RSASIGMD5 }, - { "^2\\.3\\.", SSH_BUG_DEBUG|SSH_BUG_RSASIGMD5 }, - { "^2\\.[2-9]\\.", SSH_BUG_DEBUG }, - { "^3\\.0\\.", SSH_BUG_DEBUG }, - { "^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 }, + { "1.3.2*", SSH_BUG_IGNOREMSG }, /* f-secure */ + { "*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; @@ -159,7 +162,7 @@ proto_spec(const char *spec) 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; @@ -180,24 +183,25 @@ proto_spec(const char *spec) 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); diff --git a/openssh/compat.h b/openssh/compat.h index b6609ef..0eeb782 100644 --- a/openssh/compat.h +++ b/openssh/compat.h @@ -1,3 +1,5 @@ +/* $OpenBSD: compat.h,v 1.30 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. * @@ -21,7 +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("$OpenBSD: compat.h,v 1.29 2001/09/20 13:50:40 markus Exp $"); */ #ifndef COMPAT_H #define COMPAT_H diff --git a/openssh/compress.c b/openssh/compress.c index a779af6..3badbf4 100644 --- a/openssh/compress.c +++ b/openssh/compress.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: compress.c,v 1.15 2001/09/27 11:58:16 markus Exp $"); +RCSID("$OpenBSD: compress.c,v 1.17 2001/12/29 21:56:01 stevesk Exp $"); #include "log.h" #include "buffer.h" @@ -55,13 +55,13 @@ void 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); + 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) inflateEnd(&incoming_stream); if (compress_init_send_called == 1) @@ -80,7 +80,7 @@ buffer_compress_uninit(void) 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 +88,13 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer) 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. */ @@ -124,15 +124,15 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer) 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); diff --git a/openssh/compress.h b/openssh/compress.h index 2721d45..e364f4b 100644 --- a/openssh/compress.h +++ b/openssh/compress.h @@ -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,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: compress.h,v 1.10 2001/06/26 17:27:23 markus Exp $"); */ - #ifndef COMPRESS_H #define COMPRESS_H diff --git a/openssh/config.guess b/openssh/config.guess index ba66165..83c544d 100755 --- a/openssh/config.guess +++ b/openssh/config.guess @@ -1,9 +1,9 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. -timestamp='2001-04-20' +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 @@ -24,8 +24,9 @@ timestamp='2001-04-20' # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. -# Written by Per Bothner . -# Please send patches to . +# 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 @@ -52,7 +53,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 +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 @@ -95,25 +96,25 @@ trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c +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 + ($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 + 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 + CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac +esac' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 8/24/94.) +# (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi @@ -127,29 +128,29 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or + # 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. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; + # + # 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}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + 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 @@ -171,6 +172,45 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # 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}'` @@ -204,6 +244,7 @@ main: 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 @@ -225,6 +266,9 @@ EOF 2-307) UNAME_MACHINE="alphaev67" ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; esac fi rm -f $dummy.s $dummy @@ -242,29 +286,11 @@ EOF Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -328,9 +354,6 @@ EOF aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${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 @@ -357,18 +380,6 @@ EOF *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; @@ -385,6 +396,7 @@ EOF 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 */ @@ -475,6 +487,7 @@ EOF 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 @@ -536,10 +549,8 @@ EOF 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + 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 @@ -548,12 +559,13 @@ EOF 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 ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include @@ -586,10 +598,10 @@ EOF 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 ;; + (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 ;; @@ -598,6 +610,7 @@ EOF echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int @@ -633,7 +646,7 @@ EOF 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; - *9??*:MPE/iX:*:*) + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) @@ -652,9 +665,6 @@ EOF parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; @@ -677,12 +687,13 @@ EOF echo xmp-cray-unicos exit 0 ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} + 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 y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' @@ -705,9 +716,6 @@ EOF FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; @@ -720,9 +728,6 @@ EOF *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; @@ -732,6 +737,9 @@ EOF 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 @@ -763,97 +771,43 @@ EOF echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) - cat >$dummy.c < /* for printf() prototype */ -int main (int argc, char *argv[]) { -#else -int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __MIPSEB__ - printf ("%s-unknown-linux-gnu\n", argv[1]); -#endif -#ifdef __MIPSEL__ - printf ("%sel-unknown-linux-gnu\n", argv[1]); -#endif - return 0; -} + 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 - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + 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:*:*) - # Determine Lib Version - cat >$dummy.c < -#if defined(__GLIBC__) -extern char __libc_version[]; -extern char __libc_release[]; -#endif -main(argc, argv) - int argc; - char *argv[]; -{ -#if defined(__GLIBC__) - printf("%s %s\n", __libc_version, __libc_release); -#else - printf("unknown\n"); -#endif - return 0; -} -EOF - LIBC="" - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null - if test "$?" = 0 ; then - ./$dummy | grep 1\.99 > /dev/null - if test "$?" = 0 ; then LIBC="libc1" ; fi - fi - rm -f $dummy.c $dummy - echo powerpc-unknown-linux-gnu${LIBC} + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) - 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 - LIBC="" - $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" ;; - esac - objdump --private-headers $dummy | \ - grep ld.so.1 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi - fi - rm -f $dummy.s $dummy + 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:*:*) @@ -883,71 +837,61 @@ EOF # 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. - ld_supported_emulations=`cd /; ld --help 2>&1 \ - | sed -ne '/supported emulations:/!d + # 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 emulations: *// + s/.*supported targets: *// s/ .*// p'` - case "$ld_supported_emulations" in - i*86linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 - ;; - elf_i*86) + case "$ld_supported_targets" in + elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; - i*86coff) + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 - ;; - esac - # Either a pre-BFD a.out linker (linux-gnuoldld) - # or one that does not give us useful --help. - # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. - # If ld does not provide *any* "supported emulations:" - # that means it is gnuoldld. - test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 - case "${UNAME_MACHINE}" in - i*86) - VENDOR=pc; - ;; - *) - VENDOR=unknown; - ;; + 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 - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); -#endif - return 0; -} + 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 - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + 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 ;; -# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions -# are messed up and put the nodename in both sysname and nodename. i*86:DYNIX/ptx:4*:*) + # 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.*) @@ -966,14 +910,13 @@ EOF echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; - i*86:*:5:7*) - # Fixed at (any) Pentium or better - UNAME_MACHINE=i586 - if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then - echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} - fi + 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 @@ -1021,7 +964,7 @@ EOF 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 | 4850:*:4.0:3.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` @@ -1067,8 +1010,8 @@ EOF echo ns32k-sni-sysv fi exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) @@ -1080,6 +1023,10 @@ EOF # 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 ;; @@ -1120,13 +1067,15 @@ EOF *: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 - echo `uname -p`-${UNAME_MACHINE}-nto-qnx exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) @@ -1172,11 +1121,18 @@ EOF *: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 < diff --git a/openssh/configure.ac b/openssh/configure.ac index 3cc9365..8884125 100644 --- a/openssh/configure.ac +++ b/openssh/configure.ac @@ -63,9 +63,10 @@ case "$host" in AC_DEFINE(BROKEN_GETADDRINFO) dnl AIX handles lastlog as part of its login message AC_DEFINE(DISABLE_LASTLOG) + AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) ;; *-*-cygwin*) - LIBS="$LIBS -lregex /usr/lib/textmode.o" + LIBS="$LIBS /usr/lib/textmode.o" AC_DEFINE(HAVE_CYGWIN) AC_DEFINE(USE_PIPES) AC_DEFINE(DISABLE_SHADOW) @@ -122,6 +123,7 @@ case "$host" in check_for_libcrypt_later=1 AC_DEFINE(DONT_TRY_OTHER_AF) AC_DEFINE(PAM_TTY_KLUDGE) + AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) inet6_default_4in6=yes ;; mips-sony-bsd|mips-sony-newsos4) @@ -184,6 +186,7 @@ mips-sony-bsd|mips-sony-newsos4) LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lc89" AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) + AC_DEFINE(USE_PIPES) ;; *-sni-sysv*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" @@ -317,45 +320,17 @@ AC_ARG_WITH(libs, ] ) -AC_ARG_WITH(pcre, - [ --with-pcre[[=PATH]] Override built in regex library with pcre - (optionally in PATH)], - [ - case "$withval" in - no) ;; - *) - if test "x$withval" != "xyes"; 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 - - AC_CHECK_HEADER(pcreposix.h, - AC_CHECK_LIB(pcre, pcre_info,[ - AC_DEFINE(HAVE_LIBPCRE) - LIBS="$LIBS -lpcreposix -lpcre" - no_comp_check=yes], - AC_MSG_ERROR([*** unable to locate pcre library ***])), - AC_MSG_ERROR([*** unable to locate pcreposix.h include file ***])) - ;; - esac - ] -) +# 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 poll.h pty.h \ + security/pam_appl.h shadow.h stddef.h stdint.h \ + strings.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h \ + sys/poll.h sys/queue.h sys/select.h sys/stat.h \ + sys/stropts.h sys/sysmacros.h sys/time.h \ + sys/ttcompat.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)) @@ -371,10 +346,25 @@ 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}" @@ -398,23 +388,6 @@ AC_ARG_WITH(zlib, AC_CHECK_LIB(z, deflate, ,AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***])) -# We don't want to check if we did an pcre override. -if test -z "$no_comp_check" ; then - AC_CHECK_FUNC(regcomp, - [ AC_DEFINE(HAVE_REGCOMP)], - [ - AC_CHECK_LIB(pcre, pcre_info, - [ - AC_DEFINE(HAVE_LIBPCRE) - LIBS="$LIBS -lpcreposix -lpcre" - ], - [ - AC_MSG_ERROR([*** No regex library found.]) - ]) - ] - ) -fi - dnl UnixWare 2.x AC_CHECK_FUNC(strcasecmp, [], [ AC_CHECK_LIB(resolv, strcasecmp, LIBS="$LIBS -lresolv") ] @@ -430,18 +403,6 @@ AC_CHECK_FUNCS(logout updwtmp logwtmp) AC_FUNC_STRFTIME -# 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 poll.h pty.h regex.h \ - security/pam_appl.h shadow.h stddef.h stdint.h \ - strings.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h \ - sys/poll.h sys/queue.h sys/select.h sys/stat.h \ - sys/stropts.h sys/sysmacros.h sys/time.h \ - sys/ttcompat.h sys/un.h time.h ttyent.h usersec.h \ - util.h utime.h utmp.h utmpx.h) - # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING(for GLOB_ALTDIRFUNC support) AC_EGREP_CPP(FOUNDIT, @@ -507,9 +468,16 @@ AC_ARG_WITH(skey, LIBS="-lskey $LIBS" SKEY_MSG="yes" - AC_CHECK_FUNC(skey_keyinfo, - [], + 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 @@ -546,7 +514,8 @@ AC_ARG_WITH(tcp-wrappers, CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi - LIBS="-lwrap $LIBS" + LIBWRAP="-lwrap" + LIBS="$LIBWRAP $LIBS" AC_MSG_CHECKING(for libwrap) AC_TRY_LINK( [ @@ -557,12 +526,14 @@ AC_ARG_WITH(tcp-wrappers, [ AC_MSG_RESULT(yes) AC_DEFINE(LIBWRAP) + AC_SUBST(LIBWRAP) TCPW_MSG="yes" ], [ AC_MSG_ERROR([*** libwrap missing]) ] ) + LIBS="$saved_LIBS" fi ] ) @@ -678,6 +649,12 @@ AC_ARG_WITH(pam, 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 ] ) @@ -865,12 +842,204 @@ else fi fi +# 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) + +# 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) + +# 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"; @@ -951,6 +1120,19 @@ if test -z "$have_int64_t" ; then ) 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 ], @@ -990,6 +1172,19 @@ if test "x$ac_cv_have_u_int64_t" = "xyes" ; then 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( @@ -1058,6 +1253,8 @@ 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( [ @@ -1587,97 +1784,6 @@ AC_CHECK_FILE("/dev/ptc", ) # Options from here on. Some of these are preset by platform above - -# Check for user-specified random device, otherwise check /dev/urandom -AC_ARG_WITH(random, - [ --with-random=FILE read entropy from FILE (default=/dev/urandom)], - [ - if test "x$withval" != "xno" ; then - RANDOM_POOL="$withval"; - AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") - fi - ], - [ - # Check for random device - AC_CHECK_FILE("/dev/urandom", - [ - RANDOM_POOL="/dev/urandom"; - AC_SUBST(RANDOM_POOL) - AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") - ] - ) - ] -) - -# Check for PRNGD/EGD pool file -AC_ARG_WITH(prngd-port, - [ --with-prngd-port=PORT read entropy from PRNGD/EGD localhost:PORT], - [ - if test ! -z "$withval" -a "x$withval" != "xno" ; then - PRNGD_PORT="$withval" - AC_DEFINE_UNQUOTED(PRNGD_PORT, $PRNGD_PORT) - fi - ] -) - -# Check for PRNGD/EGD pool file -AC_ARG_WITH(prngd-socket, - [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], - [ - if test "x$withval" != "xno" ; then - 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 -z "$RANDOM_POOL" ; 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 - ] -) - - -# detect pathnames for entropy gathering commands, if we need them -INSTALL_SSH_PRNG_CMDS="" -rm -f prng_commands -if (test -z "$RANDOM_POOL" && test -z "$PRNGD") ; then - # Use these commands to collect 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) - - INSTALL_SSH_PRNG_CMDS="yes" -fi -AC_SUBST(INSTALL_SSH_PRNG_CMDS) - - AC_ARG_WITH(mantype, [ --with-mantype=man|cat|doc Set man page type], [ @@ -1869,12 +1975,13 @@ AC_ARG_WITH(4in6, ) # 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=yes + BSD_AUTH_MSG=yes fi ] ) @@ -2141,44 +2248,25 @@ else fi -# Change default command timeout for builtin PRNG -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) - - if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS -blibpath:$blibpath" AC_MSG_WARN([Please check and edit -blibpath in LDFLAGS in Makefile]) fi -AC_EXEEXT +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 -if test ! -z "$RANDOM_POOL" ; then - RAND_MSG="Device ($RANDOM_POOL)" -else - if test ! -z "$PRNGD_PORT" ; then - RAND_MSG="PRNGD/EGD (port localhost:$PRNGD_PORT)" - elif test ! -z "$PRNGD_SOCKET" ; then - RAND_MSG="PRNGD/EGD (socket $PRNGD_SOCKET)" - else - RAND_MSG="Builtin (timeout $entropy_timeout)" - BUILTIN_RNG=1 - fi -fi - # Someone please show me a better way :) A=`eval echo ${prefix}` ; A=`eval echo ${A}` B=`eval echo ${bindir}` ; B=`eval echo ${B}` @@ -2198,7 +2286,6 @@ echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" echo " sshd default user PATH: $H" -echo " Random number collection: $RAND_MSG" echo " Manpage format: $MANTYPE" echo " PAM support: ${PAM_MSG}" echo " KerberosIV support: $KRB4_MSG" @@ -2210,9 +2297,10 @@ 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" - -if test ! -z "$bsd_auth"; then - echo " BSD Auth support: yes" +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 "" @@ -2222,27 +2310,29 @@ echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" -echo " Libraries: ${LIBS}" +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 for sshd," - echo "otherwise password authentication may fail. Example PAM control files" - echo "can be found in the contrib/ subdirectory" + 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 "$BUILTIN_RNG" ; then - echo "WARNING: you are using the builtin random number collection service." - echo "Please read WARNING.RNG and request that your OS vendor includes" - echo "/dev/random in future versions of their OS." +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 "$NO_SFTP"; then - echo "sftp-server will be disabled. Your compiler does not support" - echo "64bit integers." +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 diff --git a/openssh/contrib/README b/openssh/contrib/README index d255457..648bb2f 100644 --- a/openssh/contrib/README +++ b/openssh/contrib/README @@ -11,11 +11,10 @@ or http proxy which supports the CONNECT method (eg. Squid). In this directory ----------------- -chroot.diff: +chroot.diff: -Ricardo Cerqueira's patch to enable chrooting using the -wu-ftpd style magic home directories (containing '/./'). More details in -the head of the patch itself. +Due to the fact the patch is never in sync with the rest of the tree. It was +removed. ssh-copy-id: diff --git a/openssh/contrib/aix/README b/openssh/contrib/aix/README new file mode 100644 index 0000000..a08c084 --- /dev/null +++ b/openssh/contrib/aix/README @@ -0,0 +1,36 @@ +Overview: + +This directory contains files to build an AIX native (installp or SMIT +installable) openssh package. + + +Directions: + +./configure [options] +cd contrib/aix; ./buildbff.sh + + +Acknowledgements: + +The contents of this directory are based on Ben Lindstrom's Solaris +buildpkg.sh. Ben also supplied inventory.sh. + +Jim Abbey's (GPL'ed) lppbuild-2.1 was used to learn how to build .bff's +and for comparison with the output from this script, however no code +from lppbuild is included and it is not required for operation. + + +Other notes: + +The script treats all packages as USR packages (not ROOT+USR when +appropriate). It seems to work, though...... + + +Disclaimer: + +It is hoped that it is useful but there is no warranty. If it breaks +you get to keep both pieces. + + + - Darren Tucker (dtucker at zip dot com dot au) + 2002/03/01 diff --git a/openssh/contrib/aix/buildbff.sh b/openssh/contrib/aix/buildbff.sh new file mode 100755 index 0000000..6c7aaf4 --- /dev/null +++ b/openssh/contrib/aix/buildbff.sh @@ -0,0 +1,187 @@ +#!/bin/sh +# +# buildbff.sh: Create AIX SMIT-installable OpenSSH packages +# +# Author: Darren Tucker (dtucker at zip dot com dot au) +# This file is placed in the public domain and comes with absolutely +# no warranty. +# +# Based originally on Ben Lindstrom's buildpkg.sh for Solaris +# + +umask 022 +PKGNAME=openssh + +PATH=$PATH:`pwd` # set path for external tools +export PATH + +## Extract common info requires for the 'info' part of the package. +VERSION=`tail -1 ../../version.h | sed -e 's/.*_\([0-9]\)/\1/g' | sed 's/\"$//'` +BFFVERSION=`echo $VERSION | sed 's/p/./g'` + +echo "Building BFF for $PKGNAME $VERSION (package version $BFFVERSION)" +PKGDIR=package + +# Clean build directory and package file +rm -rf $PKGDIR +mkdir $PKGDIR +rm -f $PKGNAME-$VERSION.bff + +if [ ! -f ../../Makefile ] +then + echo "Top-level Makefile not found (did you run ./configure?)" + exit 1 +fi + +## Start by faking root install +echo "Faking root install..." +START=`pwd` +FAKE_ROOT=$START/$PKGDIR +cd ../.. +make install-nokeys DESTDIR=$FAKE_ROOT + +# +# Fill in some details, like prefix and sysconfdir +# the eval also expands variables like sysconfdir=${prefix}/etc +# provided they are eval'ed in the correct order +# +for confvar in prefix exec_prefix bindir sbindir libexecdir datadir mandir mansubdir sysconfdir piddir +do + eval $confvar=`grep "^$confvar=" Makefile | cut -d = -f 2` +done + +# Rename config files; postinstall script will copy them if necessary +for cfgfile in ssh_config sshd_config ssh_prng_cmds +do + mv $FAKE_ROOT/$sysconfdir/$cfgfile $FAKE_ROOT/$sysconfdir/$cfgfile.default +done + +# +# Generate lpp control files. +# working dir is $FAKE_ROOT but files are generated in contrib/aix +# and moved into place just before creation of .bff +# +cd $FAKE_ROOT +echo Generating LPP control files +find . ! -name . -print >../openssh.al +inventory.sh >../openssh.inventory +cp ../../../LICENCE ../openssh.copyright + +# +# Create postinstall script +# +cat <>../openssh.post_i +#!/bin/sh + +# Create configs from defaults if necessary +for cfgfile in ssh_config sshd_config ssh_prng_cmds +do + if [ ! -f $sysconfdir/\$cfgfile ] + then + echo "Creating \$cfgfile from default" + cp $sysconfdir/\$cfgfile.default $sysconfdir/\$cfgfile + else + echo "\$cfgfile already exists." + fi +done + +# Generate keys unless they already exist +if [ -f "$sysconfdir/ssh_host_key" ] ; then + echo "$sysconfdir/ssh_host_key already exists, skipping." +else + $bindir/ssh-keygen -t rsa1 -f $sysconfdir/ssh_host_key -N "" +fi +if [ -f $sysconfdir/ssh_host_dsa_key ] ; then + echo "$sysconfdir/ssh_host_dsa_key already exists, skipping." +else + $bindir/ssh-keygen -t dsa -f $sysconfdir/ssh_host_dsa_key -N "" +fi +if [ -f $sysconfdir/ssh_host_rsa_key ] ; then + echo "$sysconfdir/ssh_host_rsa_key already exists, skipping." +else + $bindir/ssh-keygen -t rsa -f $sysconfdir/ssh_host_rsa_key -N "" +fi + +# Add to system startup if required +if grep $sbindir/sshd /etc/rc.tcpip >/dev/null +then + echo "sshd found in rc.tcpip, not adding." +else + echo >>/etc/rc.tcpip + echo "echo Starting sshd" >>/etc/rc.tcpip + echo "$sbindir/sshd" >>/etc/rc.tcpip +fi +EOF + +# +# Create liblpp.a and move control files into it +# +echo Creating liblpp.a +( + cd .. + for i in al copyright inventory post_i + do + ar -r liblpp.a openssh.$i + rm openssh.$i + done +) + +# +# Create lpp_name +# +# This will end up looking something like: +# 4 R I OpenSSH { +# OpenSSH 3.0.2.1 1 N U en_US OpenSSH 3.0.2p1 Portable for AIX +# [ +# % +# /usr/local/bin 8073 +# /usr/local/etc 189 +# /usr/local/libexec 185 +# /usr/local/man/man1 145 +# /usr/local/man/man8 83 +# /usr/local/sbin 2105 +# /usr/local/share 3 +# % +# ] +echo Creating lpp_name +cat <../lpp_name +4 R I $PKGNAME { +$PKGNAME $BFFVERSION 1 N U en_US OpenSSH $VERSION Portable for AIX +[ +% +EOF + +for i in $bindir $sysconfdir $libexecdir $mandir/man1 $mandir/man8 $sbindir $datadir +do + # get size in 512 byte blocks + size=`du $FAKE_ROOT/$i | awk '{print $1}'` + echo "$i $size" >>../lpp_name +done + +echo '%' >>../lpp_name +echo ']' >>../lpp_name +echo '}' >>../lpp_name + +# +# Move pieces into place +# +mkdir -p usr/lpp/openssh +mv ../liblpp.a usr/lpp/openssh +mv ../lpp_name . + +# +# Now invoke backup to create .bff file +# note: lpp_name needs to be the first file do we generate the +# file list on the fly and feed it to backup using -i +# +echo Creating $PKGNAME-$VERSION.bff with backup... +( + echo "./lpp_name" + find . ! -name lpp_name -a ! -name . -print +) | backup -i -q -f ../$PKGNAME-$VERSION.bff $filelist + +cd .. + +rm -rf $PKGDIR +echo $0: done. + diff --git a/openssh/contrib/aix/inventory.sh b/openssh/contrib/aix/inventory.sh new file mode 100755 index 0000000..aa44ab9 --- /dev/null +++ b/openssh/contrib/aix/inventory.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# inventory.sh +# +# Originall written by Ben Lindstrom, modified by Darren Tucker to use perl +# +# This will produced and AIX package inventory file, which looks like: +# +# /usr/local/bin: +# class=apply,inventory,openssh +# owner=root +# group=system +# mode=755 +# type=DIRECTORY +# /usr/local/bin/slogin: +# class=apply,inventory,openssh +# owner=root +# group=system +# mode=777 +# type=SYMLINK +# target=ssh +# /usr/local/share/Ssh.bin: +# class=apply,inventory,openssh +# owner=root +# group=system +# mode=644 +# type=FILE +# size=VOLATILE +# checksum=VOLATILE + +find . ! -name . -print | perl -ne '{ + chomp; + if ( -l $_ ) { + ($dev,$ino,$mod,$nl,$uid,$gid,$rdev,$sz,$at,$mt,$ct,$bsz,$blk)=lstat; + } else { + ($dev,$ino,$mod,$nl,$uid,$gid,$rdev,$sz,$at,$mt,$ct,$bsz,$blk)=stat; + } + + # Start to display inventory information + $name = $_; + $name =~ s|^.||; # Strip leading dot from path + print "$name:\n"; + print "\tclass=apply,inventory,openssh\n"; + print "\towner=root\n"; + print "\tgroup=system\n"; + printf "\tmode=%lo\n", $mod & 07777; # Mask perm bits + + if ( -l $_ ) { + # Entry is SymLink + print "\ttype=SYMLINK\n"; + printf "\ttarget=%s\n", readlink($_); + } elsif ( -f $_ ) { + # Entry is File + print "\ttype=FILE\n"; + print "\tsize=VOLATILE\n"; + print "\tchecksum=VOLATILE\n"; + } elsif ( -d $_ ) { + # Entry is Directory + print "\ttype=DIRECTORY\n"; + } +}' diff --git a/openssh/contrib/caldera/openssh.spec b/openssh/contrib/caldera/openssh.spec index b11e549..e2077bf 100644 --- a/openssh/contrib/caldera/openssh.spec +++ b/openssh/contrib/caldera/openssh.spec @@ -1,6 +1,6 @@ %define use-stable 1 %if %{use-stable} - %define version 3.0.2p1 + %define version 3.1p1 %define cvs %{nil} %define release 1 %else diff --git a/openssh/contrib/cygwin/README b/openssh/contrib/cygwin/README index dfe1786..60d3916 100644 --- a/openssh/contrib/cygwin/README +++ b/openssh/contrib/cygwin/README @@ -1,5 +1,13 @@ This package is the actual port of OpenSSH to Cygwin 1.3. +=========================================================================== +Important change since 3.0.1p1-2: + +This version introduces the ability to register sshd as service on +Windows 9x/Me systems. This is done only when the options -D and/or +-d are not given. +=========================================================================== + =========================================================================== Important change since 2.9p2: @@ -75,12 +83,12 @@ If you start sshd as deamon via cygrunsrv.exe you MUST give the If starting via inetd, copy sshd to eg. /usr/sbin/in.sshd and add the following line to your inetd.conf file: -sshd stream tcp nowait root /usr/sbin/in.sshd sshd -i +ssh stream tcp nowait root /usr/sbin/in.sshd sshd -i Moreover you'll have to add the following line to your ${SYSTEMROOT}/system32/drivers/etc/services file: - sshd 22/tcp #SSH daemon + ssh 22/tcp #SSH daemon =========================================================================== The following restrictions only apply to Cygwin versions up to 1.3.1 @@ -162,12 +170,10 @@ configure are used for the Cygwin binary distribution: --prefix=/usr \ --sysconfdir=/etc \ - --libexecdir='${exec_prefix}/sbin \ - --with-pcre + --libexecdir='${exec_prefix}/sbin' You must have installed the zlib, openssl and regex packages to -be able to build OpenSSH! The `--with-pcre' option requires -the installation of the pcre package. +be able to build OpenSSH! Please send requests, error reports etc. to cygwin@cygwin.com. diff --git a/openssh/contrib/gnome-ssh-askpass.c b/openssh/contrib/gnome-ssh-askpass.c index 27e5cca..7cece56 100644 --- a/openssh/contrib/gnome-ssh-askpass.c +++ b/openssh/contrib/gnome-ssh-askpass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Damien Miller. All rights reserved. + * Copyright (c) 2000-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 @@ -22,6 +22,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * This is a simple GNOME SSH passphrase grabber. To use it, set the + * environment variable SSH_ASKPASS to point to the location of + * gnome-ssh-askpass before calling "ssh-add < /dev/null". + * + * There is only two run-time options: if you set the environment variable + * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab + * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the + * pointer will be grabbed too. These may have some benefit to security if + * you don't trust your X server. We grab the keyboard always. + */ + /* * Compile with: * @@ -57,10 +69,12 @@ passphrase_dialog(char *message) { char *passphrase; char **messages; - int result, i; - + int result, i, grab_server, grab_pointer; GtkWidget *dialog, *entry, *label; + grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); + grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); + dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); @@ -89,9 +103,10 @@ passphrase_dialog(char *message) gtk_widget_show_all(dialog); /* Grab focus */ - XGrabServer(GDK_DISPLAY()); - if (gdk_pointer_grab(dialog->window, TRUE, 0, NULL, NULL, - GDK_CURRENT_TIME)) + if (grab_server) + XGrabServer(GDK_DISPLAY()); + if (grab_pointer && gdk_pointer_grab(dialog->window, TRUE, 0, + NULL, NULL, GDK_CURRENT_TIME)) goto nograb; if (gdk_keyboard_grab(dialog->window, FALSE, GDK_CURRENT_TIME)) goto nograbkb; @@ -103,8 +118,10 @@ passphrase_dialog(char *message) result = gnome_dialog_run(GNOME_DIALOG(dialog)); /* Ungrab */ - XUngrabServer(GDK_DISPLAY()); - gdk_pointer_ungrab(GDK_CURRENT_TIME); + if (grab_server) + XUngrabServer(GDK_DISPLAY()); + if (grab_pointer) + gdk_pointer_ungrab(GDK_CURRENT_TIME); gdk_keyboard_ungrab(GDK_CURRENT_TIME); gdk_flush(); @@ -126,7 +143,8 @@ passphrase_dialog(char *message) nograbkb: gdk_pointer_ungrab(GDK_CURRENT_TIME); nograb: - XUngrabServer(GDK_DISPLAY()); + if (grab_server) + XUngrabServer(GDK_DISPLAY()); gnome_dialog_close(GNOME_DIALOG(dialog)); report_failed_grab(); diff --git a/openssh/contrib/redhat/openssh.spec b/openssh/contrib/redhat/openssh.spec index 8ab6859..c36b651 100644 --- a/openssh/contrib/redhat/openssh.spec +++ b/openssh/contrib/redhat/openssh.spec @@ -1,5 +1,5 @@ # Version of OpenSSH -%define oversion 3.0.2p1 +%define oversion 3.1p1 # Version of ssh-askpass %define aversion 1.2.4.1 diff --git a/openssh/contrib/suse/openssh.spec b/openssh/contrib/suse/openssh.spec index b3bc0c0..88b0e81 100644 --- a/openssh/contrib/suse/openssh.spec +++ b/openssh/contrib/suse/openssh.spec @@ -1,6 +1,6 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 3.0.2p1 +Version: 3.1p1 URL: http://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz diff --git a/openssh/crc32.h b/openssh/crc32.h index bdabc1b..cd1832f 100644 --- a/openssh/crc32.h +++ b/openssh/crc32.h @@ -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,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: crc32.h,v 1.12 2001/06/26 17:27:23 markus Exp $"); */ - #ifndef CRC32_H #define CRC32_H diff --git a/openssh/deattack.c b/openssh/deattack.c index 1a89be4..0442501 100644 --- a/openssh/deattack.c +++ b/openssh/deattack.c @@ -1,5 +1,3 @@ -/* $OpenBSD: deattack.c,v 1.14 2001/06/23 15:12:18 itojun 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) @@ -85,9 +86,9 @@ detect_attack(u_char *buf, u_int32_t len, u_char *IV) { 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) || @@ -134,7 +135,7 @@ detect_attack(u_char *buf, u_int32_t len, u_char *IV) 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)) diff --git a/openssh/defines.h b/openssh/defines.h index 3c2287e..4caea9b 100644 --- a/openssh/defines.h +++ b/openssh/defines.h @@ -141,6 +141,14 @@ enum # 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 */ @@ -161,7 +169,11 @@ typedef char int8_t; 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 */ @@ -194,7 +206,11 @@ typedef unsigned char u_int8_t; 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 @@ -269,6 +285,11 @@ 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 @@ -356,6 +377,16 @@ struct winsize { #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 @@ -436,7 +467,7 @@ struct winsize { #endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ #if !defined(HAVE_ATEXIT) && defined(HAVE_ON_EXIT) -# define atexit(a, NULL) on_exit(a, NULL) +# define atexit(a) on_exit(a, NULL) #else # if defined(HAVE_XATEXIT) # define atexit(a) xatexit(a) diff --git a/openssh/dh.c b/openssh/dh.c index fa2508a..33187e0 100644 --- a/openssh/dh.c +++ b/openssh/dh.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: dh.c,v 1.17 2001/06/23 15:12:18 itojun Exp $"); +RCSID("$OpenBSD: dh.c,v 1.21 2002/03/06 00:23:27 markus Exp $"); #include "xmalloc.h" @@ -78,8 +78,10 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) 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 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) 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); @@ -120,8 +122,8 @@ choose_dh(int min, int wantbits, int max) 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; @@ -150,8 +152,8 @@ choose_dh(int min, int wantbits, int max) 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; @@ -201,9 +203,8 @@ dh_gen_key(DH *dh, int need) 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)) @@ -225,9 +226,8 @@ dh_new_group_asc(const char *gen, const char *modulus) { 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"); @@ -247,9 +247,8 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus) { 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; diff --git a/openssh/dispatch.c b/openssh/dispatch.c index 64873d5..ce32bc2 100644 --- a/openssh/dispatch.c +++ b/openssh/dispatch.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: dispatch.c,v 1.11 2001/06/10 11:29:20 markus Exp $"); +RCSID("$OpenBSD: dispatch.c,v 1.15 2002/01/11 13:39:36 markus Exp $"); #include "ssh1.h" #include "ssh2.h" @@ -37,18 +37,40 @@ RCSID("$OpenBSD: dispatch.c,v 1.11 2001/06/10 11:29:20 markus Exp $"); 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) { - fatal("dispatch_protocol_error: type %d plen %d", type, plen); + 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; @@ -57,18 +79,18 @@ void 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) diff --git a/openssh/dispatch.h b/openssh/dispatch.h index 7b94032..a82e216 100644 --- a/openssh/dispatch.h +++ b/openssh/dispatch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.h,v 1.6 2001/06/26 17:27:23 markus 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 @@ enum { DISPATCH_NONBLOCK }; -typedef void dispatch_fn(int, int, void *); +typedef void dispatch_fn(int, u_int32_t, void *); 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, int, void *); +void dispatch_protocol_error(int, u_int32_t, void *); +void dispatch_protocol_ignore(int, u_int32_t, void *); diff --git a/openssh/entropy.c b/openssh/entropy.c index 9588f79..9de2921 100644 --- a/openssh/entropy.c +++ b/openssh/entropy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Damien Miller. All rights reserved. + * 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 @@ -25,14 +25,8 @@ #include "includes.h" #include -#include #include -/* SunOS 4.4.4 needs this */ -#ifdef HAVE_FLOATINGPOINT_H -# include -#endif /* HAVE_FLOATINGPOINT_H */ - #include "ssh.h" #include "misc.h" #include "xmalloc.h" @@ -40,878 +34,117 @@ #include "pathnames.h" #include "log.h" -RCSID("$Id$"); - -#ifndef offsetof -# define offsetof(type, member) ((size_t) &((type *)0)->member) -#endif - -/* Number of times to pass through command list gathering entropy */ -#define NUM_ENTROPY_RUNS 1 - -/* Scale entropy estimates back by this amount on subsequent runs */ -#define SCALE_PER_RUN 10.0 - -/* Minimum number of commands to be considered valid */ -#define MIN_ENTROPY_SOURCES 16 - -#define WHITESPACE " \t\n" - -#ifndef RUSAGE_SELF -# define RUSAGE_SELF 0 -#endif -#ifndef RUSAGE_CHILDREN -# define RUSAGE_CHILDREN 0 -#endif - -#if defined(_POSIX_SAVED_IDS) && !defined(BROKEN_SAVED_UIDS) -# define SAVED_IDS_WORK_WITH_SETEUID -#endif - -static void -check_openssl_version(void) -{ - if (SSLeay() != OPENSSL_VERSION_NUMBER) - fatal("OpenSSL version mismatch. Built against %lx, you " - "have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); -} - -#if defined(PRNGD_SOCKET) || defined(PRNGD_PORT) -# define USE_PRNGD -#endif - -#if defined(USE_PRNGD) || defined(RANDOM_POOL) - -#ifdef USE_PRNGD -/* Collect entropy from PRNGD/EGD */ -int -get_random_bytes(unsigned char *buf, int len) -{ - int fd; - char msg[2]; -#ifdef PRNGD_PORT - struct sockaddr_in addr; -#else - struct sockaddr_un addr; -#endif - int addr_len, rval, errors; - mysig_t old_sigpipe; - - memset(&addr, '\0', sizeof(addr)); - -#ifdef PRNGD_PORT - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(PRNGD_PORT); - addr_len = sizeof(struct sockaddr_in); -#else /* use IP socket PRNGD_SOCKET instead */ - /* Sanity checks */ - if (sizeof(PRNGD_SOCKET) > sizeof(addr.sun_path)) - fatal("Random pool path is too long"); - if (len > 255) - fatal("Too many bytes to read from PRNGD"); - - addr.sun_family = AF_UNIX; - strlcpy(addr.sun_path, PRNGD_SOCKET, sizeof(addr.sun_path)); - addr_len = offsetof(struct sockaddr_un, sun_path) + - sizeof(PRNGD_SOCKET); -#endif - - old_sigpipe = mysignal(SIGPIPE, SIG_IGN); - - errors = rval = 0; -reopen: -#ifdef PRNGD_PORT - fd = socket(addr.sin_family, SOCK_STREAM, 0); - if (fd == -1) { - error("Couldn't create AF_INET socket: %s", strerror(errno)); - goto done; - } -#else - fd = socket(addr.sun_family, SOCK_STREAM, 0); - if (fd == -1) { - error("Couldn't create AF_UNIX socket: %s", strerror(errno)); - goto done; - } -#endif - - if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) { -#ifdef PRNGD_PORT - error("Couldn't connect to PRNGD port %d: %s", - PRNGD_PORT, strerror(errno)); -#else - error("Couldn't connect to PRNGD socket \"%s\": %s", - addr.sun_path, strerror(errno)); -#endif - 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 = 1; -done: - mysignal(SIGPIPE, old_sigpipe); - if (fd != -1) - close(fd); - return(rval); -} -#else /* !USE_PRNGD */ -#ifdef RANDOM_POOL -/* Collect entropy from /dev/urandom or pipe */ -static int -get_random_bytes(unsigned char *buf, int len) -{ - int random_pool; - - random_pool = open(RANDOM_POOL, O_RDONLY); - if (random_pool == -1) { - error("Couldn't open random pool \"%s\": %s", - RANDOM_POOL, strerror(errno)); - return(0); - } - - if (atomicio(read, random_pool, buf, len) != len) { - error("Couldn't read from random pool \"%s\": %s", - RANDOM_POOL, strerror(errno)); - close(random_pool); - return(0); - } - - close(random_pool); - - return(1); -} -#endif /* RANDOM_POOL */ -#endif /* USE_PRNGD */ - /* - * Seed OpenSSL's random number pool from Kernel random number generator - * or PRNGD/EGD + * 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. */ -void -seed_rng(void) -{ - unsigned char buf[32]; - debug("Seeding random number generator"); - - if (!get_random_bytes(buf, sizeof(buf))) { - if (!RAND_status()) - fatal("Entropy collection failed and entropy exhausted"); - } else { - RAND_add(buf, sizeof(buf), sizeof(buf)); - } +RCSID("$Id$"); - memset(buf, '\0', sizeof(buf)); -} +#ifndef OPENSSL_PRNG_ONLY +#define RANDOM_SEED_SIZE 48 +static uid_t original_uid, original_euid; +#endif void -init_rng(void) -{ - check_openssl_version(); -} - -#else /* defined(USE_PRNGD) || defined(RANDOM_POOL) */ - -/* - * FIXME: proper entropy estimations. All current values are guesses - * FIXME: (ATL) do estimates at compile time? - * FIXME: More entropy sources - */ - -/* slow command timeouts (all in milliseconds) */ -/* static int entropy_timeout_default = ENTROPY_TIMEOUT_MSEC; */ -static int entropy_timeout_current = ENTROPY_TIMEOUT_MSEC; - -static int prng_seed_saved = 0; -static int prng_initialised = 0; -uid_t original_uid; - -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[5]; - /* full command string (debug) */ - char *cmdstring; -} entropy_source_t; - -double stir_from_system(void); -double stir_from_programs(void); -double stir_gettimeofday(double entropy_estimate); -double stir_clock(double entropy_estimate); -double stir_rusage(int who, double entropy_estimate); -double hash_output_from_command(entropy_source_t *src, char *hash); - -/* this is initialised from a file, by prng_read_commands() */ -entropy_source_t *entropy_sources = NULL; - -double -stir_from_system(void) -{ - double total_entropy_estimate; - long int i; - - total_entropy_estimate = 0; - - i = getpid(); - RAND_add(&i, sizeof(i), 0.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 i; - int c; - double entropy_estimate; - double total_entropy_estimate; - char hash[SHA_DIGEST_LENGTH]; - - total_entropy_estimate = 0; - for(i = 0; i < NUM_ENTROPY_RUNS; i++) { - c = 0; - while (entropy_sources[c].path != NULL) { - - if (!entropy_sources[c].badness) { - /* Hash output from command */ - entropy_estimate = hash_output_from_command(&entropy_sources[c], hash); - - /* Scale back entropy estimate according to command's rate */ - entropy_estimate *= entropy_sources[c].rate; - - /* Upper bound of entropy estimate is SHA_DIGEST_LENGTH */ - if (entropy_estimate > SHA_DIGEST_LENGTH) - entropy_estimate = SHA_DIGEST_LENGTH; - - /* Scale back estimates for subsequent passes through list */ - entropy_estimate /= SCALE_PER_RUN * (i + 1.0); - - /* Stir it in */ - RAND_add(hash, sizeof(hash), entropy_estimate); - - debug3("Got %0.2f bytes of entropy from '%s'", entropy_estimate, - entropy_sources[c].cmdstring); - - total_entropy_estimate += entropy_estimate; - - /* Execution times should be a little unpredictable */ - total_entropy_estimate += stir_gettimeofday(0.05); - total_entropy_estimate += stir_clock(0.05); - total_entropy_estimate += stir_rusage(RUSAGE_SELF, 0.1); - total_entropy_estimate += stir_rusage(RUSAGE_CHILDREN, 0.1); - } else { - debug2("Command '%s' disabled (badness %d)", - entropy_sources[c].cmdstring, entropy_sources[c].badness); - - if (entropy_sources[c].badness > 0) - entropy_sources[c].badness--; - } - - c++; - } - } - - return(total_entropy_estimate); -} - -double -stir_gettimeofday(double entropy_estimate) -{ - struct timeval tv; - - if (gettimeofday(&tv, NULL) == -1) - fatal("Couldn't gettimeofday: %s", strerror(errno)); - - RAND_add(&tv, sizeof(tv), entropy_estimate); - - return(entropy_estimate); -} - -double -stir_clock(double entropy_estimate) -{ -#ifdef HAVE_CLOCK - clock_t c; - - c = clock(); - RAND_add(&c, sizeof(c), entropy_estimate); - - return(entropy_estimate); -#else /* _HAVE_CLOCK */ - return(0); -#endif /* _HAVE_CLOCK */ -} - -double -stir_rusage(int who, double entropy_estimate) -{ -#ifdef HAVE_GETRUSAGE - struct rusage ru; - - if (getrusage(who, &ru) == -1) - return(0); - - RAND_add(&ru, sizeof(ru), entropy_estimate); - - return(entropy_estimate); -#else /* _HAVE_GETRUSAGE */ - return(0); -#endif /* _HAVE_GETRUSAGE */ -} - - -static int -_get_timeval_msec_difference(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_output_from_command(entropy_source_t *src, char *hash) +seed_rng(void) { - static int devnull = -1; +#ifndef OPENSSL_PRNG_ONLY + int devnull; int p[2]; - fd_set rdset; - int cmd_eof = 0, error_abort = 0; - struct timeval tv_start, tv_current; - int msec_elapsed = 0; pid_t pid; - int status; - char buf[16384]; - int bytes_read; - int total_bytes_read; - SHA_CTX sha; - - 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); - - setuid(original_uid); - 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); - total_bytes_read = 0; - - while (!error_abort && !cmd_eof) { - int ret; - struct timeval tv; - int msec_remaining; - - (void) gettimeofday(&tv_current, 0); - msec_elapsed = _get_timeval_msec_difference(&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); -} - -/* - * prng seedfile functions - */ -int -prng_check_seedfile(char *filename) { + int ret; + unsigned char buf[RANDOM_SEED_SIZE]; - struct stat st; - - /* FIXME raceable: eg replace seed between this stat and subsequent open */ - /* Not such a problem because we don't trust the seed file anyway */ - if (lstat(filename, &st) == -1) { - /* Give up on hard errors */ - if (errno != ENOENT) - debug("WARNING: Couldn't stat random seed file \"%s\": %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 == original_uid)) { - 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[1024]; - char filename[1024]; - struct passwd *pw; - - /* Don't bother if we have already saved a seed */ - if (prng_seed_saved) + if (RAND_status() == 1) { + debug3("RNG is ready, skipping seeding"); return; - - setuid(original_uid); - - prng_seed_saved = 1; - - pw = getpwuid(original_uid); - if (pw == NULL) - fatal("Couldn't get password entry for current user (%i): %s", - original_uid, 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[1024]; - char filename[1024]; - struct passwd *pw; - - pw = getpwuid(original_uid); - if (pw == NULL) - fatal("Couldn't get password entry for current user (%i): %s", - original_uid, 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 not valid, 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) -{ - FILE *f; - char *cp; - char line[1024]; - char cmd[1024]; - char path[256]; - int linenum; - int num_cmds = 64; - int cur_cmd = 0; - double est; - entropy_source_t *entcmd; - - f = fopen(cmdfilename, "r"); - if (!f) { - fatal("couldn't read entropy commands file %.100s: %.100s", - cmdfilename, strerror(errno)); - } - - entcmd = (entropy_source_t *)xmalloc(num_cmds * sizeof(entropy_source_t)); - memset(entcmd, '\0', num_cmds * sizeof(entropy_source_t)); + debug3("Seeing PRNG from %s", SSH_RAND_HELPER); - /* Read in file */ - linenum = 0; - while (fgets(line, sizeof(line), f)) { - int arg; - char *argv; - - linenum++; - - /* skip leading whitespace, test for blank line or comment */ - cp = line + strspn(line, WHITESPACE); - if ((*cp == 0) || (*cp == '#')) - continue; /* done with this line */ - - /* First non-whitespace char should be double quote delimiting */ - /* 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, &argv); - - /* 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; - argv = NULL; - do { - char *s = (char*)xmalloc(strlen(cp) + 1); - strncpy(s, cp, strlen(cp) + 1); - entcmd[cur_cmd].args[arg] = s; - arg++; - } while ((arg < 5) && (cp = strtok(NULL, WHITESPACE))); - - if (strtok(NULL, WHITESPACE)) - error("ignored extra command elements (max 5), %.100s line %d", - 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_source_t)); + 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)); + + 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 && + setuid(original_uid) == -1) { + fprintf(stderr, "(rand child) setuid: %s\n", + 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); } - /* zero the last entry */ - memset(&entcmd[cur_cmd], '\0', sizeof(entropy_source_t)); - - /* trim to size */ - entropy_sources = xrealloc(entcmd, (cur_cmd+1) * sizeof(entropy_source_t)); - - debug("Loaded %d entropy commands from %.100s", cur_cmd, cmdfilename); - - return (cur_cmd >= MIN_ENTROPY_SOURCES); -} - -/* - * Write a keyfile at exit - */ -void -prng_seed_cleanup(void *junk) -{ - prng_write_seedfile(); -} - -/* - * Conditionally Seed OpenSSL's random number pool from - * syscalls and program output - */ -void -seed_rng(void) -{ - mysig_t old_sigchld_handler; + close(devnull); + close(p[1]); - if (!prng_initialised) - fatal("RNG not initialised"); + 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"); - /* Make sure some other sigchld handler doesn't reap our entropy */ - /* commands */ - old_sigchld_handler = mysignal(SIGCHLD, SIG_DFL); + close(p[0]); - debug("Seeded RNG with %i bytes from programs", - (int)stir_from_programs()); - debug("Seeded RNG with %i bytes from system calls", - (int)stir_from_system()); + if (waitpid(pid, &ret, 0) == -1) + fatal("Couldn't wait for ssh-rand-helper completion: %s", + strerror(errno)); - if (!RAND_status()) - fatal("Not enough entropy in RNG"); + /* 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); - mysignal(SIGCHLD, old_sigchld_handler); + RAND_add(buf, sizeof(buf), sizeof(buf)); + memset(buf, '\0', sizeof(buf)); - if (!RAND_status()) - fatal("Couldn't initialise builtin random number generator -- exiting."); +#endif /* OPENSSL_PRNG_ONLY */ + if (RAND_status() != 1) + fatal("PRNG is not seeded"); } void -init_rng(void) +init_rng(void) { - int original_euid; - - check_openssl_version(); - - original_uid = getuid(); - original_euid = geteuid(); - - /* Read in collection commands */ - if (!prng_read_commands(SSH_PRNG_COMMAND_FILE)) - fatal("PRNG initialisation failed -- exiting."); - - /* Set ourselves up to save a seed upon exit */ - prng_seed_saved = 0; - - /* Give up privs while reading seed file */ -#ifdef SAVED_IDS_WORK_WITH_SETEUID - if ((original_uid != original_euid) && (seteuid(original_uid) == -1)) - fatal("Couldn't give up privileges"); -#else /* SAVED_IDS_WORK_WITH_SETEUID */ /* - * Propagate the privileged uid to all of our uids. - * Set the effective uid to the given (unprivileged) uid. + * OpenSSL version numbers: MNNFFPPS: major minor fix patch status + * We match major, minor, fix and status (not patch) */ - if (original_uid != original_euid && (setuid(original_euid) == -1 || - seteuid(original_uid) == -1)) - fatal("Couldn't give up privileges"); -#endif /* SAVED_IDS_WORK_WITH_SETEUID */ - - prng_read_seedfile(); - -#ifdef SAVED_IDS_WORK_WITH_SETEUID - if ((original_uid != original_euid) && (seteuid(original_euid) == -1)) - fatal("Couldn't restore privileges"); -#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. - */ - if (original_uid != original_euid && (seteuid(original_euid) == -1 || - setuid(original_uid) == -1)) - fatal("Couldn't restore privileges"); -#endif /* SAVED_IDS_WORK_WITH_SETEUID */ - - fatal_add_cleanup(prng_seed_cleanup, NULL); - atexit(prng_write_seedfile); + if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); - prng_initialised = 1; +#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 } -#endif /* defined(USE_PRNGD) || defined(RANDOM_POOL) */ diff --git a/openssh/fatal.c b/openssh/fatal.c new file mode 100644 index 0000000..9e7d160 --- /dev/null +++ b/openssh/fatal.c @@ -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(); +} diff --git a/openssh/getput.h b/openssh/getput.h index 1a19d22..20cf8f2 100644 --- a/openssh/getput.h +++ b/openssh/getput.h @@ -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 @@ -11,8 +13,6 @@ * 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 diff --git a/openssh/groupaccess.c b/openssh/groupaccess.c index cbfe720..66dfa68 100644 --- a/openssh/groupaccess.c +++ b/openssh/groupaccess.c @@ -1,5 +1,3 @@ -/* $OpenBSD: groupaccess.c,v 1.4 2001/06/26 17:27:23 markus 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" diff --git a/openssh/hostfile.c b/openssh/hostfile.c index eeed920..cefff8d 100644 --- a/openssh/hostfile.c +++ b/openssh/hostfile.c @@ -36,7 +36,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: hostfile.c,v 1.28 2001/06/25 08:25:37 markus Exp $"); +RCSID("$OpenBSD: hostfile.c,v 1.29 2001/12/18 10:04:21 jakob Exp $"); #include "packet.h" #include "match.h" @@ -49,7 +49,7 @@ RCSID("$OpenBSD: hostfile.c,v 1.28 2001/06/25 08:25:37 markus Exp $"); * pointer over the key. Skips any whitespace at the beginning and at end. */ -static int +int hostfile_read_key(char **cpp, u_int *bitsp, Key *ret) { char *cp; @@ -71,17 +71,6 @@ hostfile_read_key(char **cpp, u_int *bitsp, Key *ret) 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; -} - static int hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum) { diff --git a/openssh/hostfile.h b/openssh/hostfile.h index 05ef691..0244fdb 100644 --- a/openssh/hostfile.h +++ b/openssh/hostfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.h,v 1.9 2001/06/26 17:27:23 markus Exp $ */ +/* $OpenBSD: hostfile.h,v 1.10 2001/12/18 10:04:21 jakob Exp $ */ /* * Author: Tatu Ylonen @@ -18,9 +18,9 @@ typedef enum { HOST_OK, HOST_NEW, HOST_CHANGED } HostStatus; +int hostfile_read_key(char **, u_int *, Key *); HostStatus check_host_in_hostfile(const char *, const char *, Key *, Key *, int *); int add_host_to_hostfile(const char *, const char *, Key *); -int auth_rsa_read_key(char **, u_int *, BIGNUM *, BIGNUM *); #endif diff --git a/openssh/includes.h b/openssh/includes.h index f9cf9c7..4740418 100644 --- a/openssh/includes.h +++ b/openssh/includes.h @@ -1,4 +1,4 @@ -/* $OpenBSD: includes.h,v 1.15 2001/06/08 15:25:40 markus Exp $ */ +/* $OpenBSD: includes.h,v 1.17 2002/01/26 16:44:22 stevesk Exp $ */ /* * Author: Tatu Ylonen diff --git a/openssh/kex.c b/openssh/kex.c index 1a412ce..bf8fd95 100644 --- a/openssh/kex.c +++ b/openssh/kex.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kex.c,v 1.36 2001/06/25 08:25:37 markus Exp $"); +RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $"); #include @@ -107,27 +107,23 @@ kex_prop_free(char **proposal) } static void -kex_protocol_error(int type, int plen, void *ctxt) +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); } static void -kex_clear_dispatch(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(); @@ -135,7 +131,8 @@ kex_finish(Kex *kex) 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; @@ -166,7 +163,7 @@ kex_send_kexinit(Kex *kex) } 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; @@ -187,7 +184,7 @@ kex_input_kexinit(int type, int plen, void *ctxt) xfree(packet_get_string(NULL)); packet_get_char(); packet_get_int(); - packet_done(); + packet_check_eom(); kex_kexinit_finish(kex); } @@ -205,8 +202,7 @@ kex_setup(char *proposal[PROPOSAL_MAX]) 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; } @@ -219,7 +215,7 @@ kex_kexinit_finish(Kex *kex) kex_choose_conf(kex); - switch(kex->kex_type) { + switch (kex->kex_type) { case DH_GRP1_SHA1: kexdh(kex); break; @@ -237,13 +233,14 @@ 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); } static void choose_mac(Mac *mac, char *client, char *server) @@ -346,10 +343,10 @@ kex_choose_conf(Kex *kex) 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; } @@ -364,11 +361,11 @@ 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); @@ -444,7 +441,7 @@ dump_digest(char *msg, u_char *digest, int len) 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"); diff --git a/openssh/kex.h b/openssh/kex.h index fe33921..755bf33 100644 --- a/openssh/kex.h +++ b/openssh/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.26 2001/06/26 17:27:23 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -71,6 +71,8 @@ struct Enc { char *name; Cipher *cipher; int enabled; + u_int key_len; + u_int block_size; u_char *key; u_char *iv; }; @@ -115,7 +117,7 @@ Kex *kex_setup(char *[PROPOSAL_MAX]); void kex_finish(Kex *); void kex_send_kexinit(Kex *); -void kex_input_kexinit(int, int, void *); +void kex_input_kexinit(int, u_int32_t, void *); void kex_derive_keys(Kex *, u_char *, BIGNUM *); void kexdh(Kex *); diff --git a/openssh/kexdh.c b/openssh/kexdh.c index b850a1a..eaf497c 100644 --- a/openssh/kexdh.c +++ b/openssh/kexdh.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kexdh.c,v 1.7 2001/09/17 19:27:15 stevesk Exp $"); +RCSID("$OpenBSD: kexdh.c,v 1.17 2002/02/28 15:46:33 markus Exp $"); #include #include @@ -51,7 +51,7 @@ kex_dh_hash( { 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); @@ -81,7 +81,7 @@ kex_dh_hash( 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; } @@ -97,7 +97,6 @@ kexdh_client(Kex *kex) 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,24 +114,24 @@ kexdh_client(Kex *kex) #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 (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= "); @@ -143,7 +142,7 @@ kexdh_client(Kex *kex) /* 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"); @@ -154,7 +153,8 @@ kexdh_client(Kex *kex) #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); @@ -171,7 +171,7 @@ kexdh_client(Kex *kex) 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, signature, slen, hash, 20) != 1) @@ -201,14 +201,14 @@ kexdh_server(Kex *kex) 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"); @@ -217,10 +217,10 @@ kexdh_server(Kex *kex) 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= "); @@ -244,7 +244,8 @@ kexdh_server(Kex *kex) #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); @@ -262,7 +263,7 @@ kexdh_server(Kex *kex) 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 */ diff --git a/openssh/kexgex.c b/openssh/kexgex.c index f06f2c3..61896e6 100644 --- a/openssh/kexgex.c +++ b/openssh/kexgex.c @@ -24,7 +24,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kexgex.c,v 1.9 2001/09/17 19:27:15 stevesk Exp $"); +RCSID("$OpenBSD: kexgex.c,v 1.20 2002/02/28 15:46:33 markus Exp $"); #include @@ -53,7 +53,7 @@ kexgex_hash( { 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); @@ -92,7 +92,7 @@ kexgex_hash( 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; } @@ -107,7 +107,7 @@ kexgex_client(Kex *kex) 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 +138,15 @@ kexgex_client(Kex *kex) 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,24 +169,24 @@ kexgex_client(Kex *kex) 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 (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= "); @@ -197,7 +197,7 @@ kexgex_client(Kex *kex) /* 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"); @@ -208,7 +208,8 @@ kexgex_client(Kex *kex) #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); @@ -232,7 +233,7 @@ kexgex_client(Kex *kex) /* 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, signature, slen, hash, 20) != 1) fatal("key_verify failed for server_host_key"); @@ -260,8 +261,8 @@ kexgex_server(Kex *kex) Key *server_host_key; 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"); @@ -269,8 +270,8 @@ kexgex_server(Kex *kex) 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(); @@ -289,7 +290,7 @@ kexgex_server(Kex *kex) 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", @@ -312,13 +313,13 @@ kexgex_server(Kex *kex) 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= "); @@ -342,7 +343,8 @@ kexgex_server(Kex *kex) #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); @@ -365,7 +367,7 @@ kexgex_server(Kex *kex) 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 */ diff --git a/openssh/key.c b/openssh/key.c index 57df5b9..cda9157 100644 --- a/openssh/key.c +++ b/openssh/key.c @@ -32,7 +32,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: key.c,v 1.33 2001/10/04 14:34:16 markus Exp $"); +RCSID("$OpenBSD: key.c,v 1.41 2002/02/28 15:46:33 markus Exp $"); #include @@ -60,17 +60,25 @@ key_new(int type) 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: @@ -88,15 +96,22 @@ key_new_private(int type) 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; @@ -155,13 +170,13 @@ key_equal(Key *a, Key *b) } static u_char* -key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) +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 +216,7 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) 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 { @@ -212,14 +226,14 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) } static char* -key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) +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); @@ -229,7 +243,7 @@ key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) } static char* -key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len) +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 +294,12 @@ key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) { 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; @@ -371,7 +385,7 @@ key_read(Key *ret, char **cpp) cp = *cpp; - switch(ret->type) { + switch (ret->type) { case KEY_RSA1: /* Get number of bits. */ if (*cp < '0' || *cp > '9') @@ -420,14 +434,15 @@ key_read(Key *ret, char **cpp) 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 +469,9 @@ key_read(Key *ret, char **cpp) #endif } /*XXXX*/ + key_free(k); if (success != 1) break; - key_free(k); /* advance cp: skip whitespace and data */ while (*cp == ' ' || *cp == '\t') cp++; @@ -473,8 +488,9 @@ key_read(Key *ret, char **cpp) 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 +504,6 @@ key_write(Key *key, FILE *f) } } 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); @@ -532,7 +546,8 @@ key_ssh_name(Key *k) return "ssh-unknown"; } u_int -key_size(Key *k){ +key_size(Key *k) +{ switch (k->type) { case KEY_RSA1: case KEY_RSA: @@ -615,15 +630,15 @@ key_from_private(Key *k) 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 +654,7 @@ key_names_valid2(const char *names) 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: @@ -668,7 +683,7 @@ key_from_blob(u_char *blob, int blen) 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 +729,7 @@ key_to_blob(Key *key, u_char **blobp, u_int *lenp) 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); @@ -747,10 +762,10 @@ key_to_blob(Key *key, u_char **blobp, u_int *lenp) 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; @@ -767,13 +782,13 @@ key_sign( 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) { if (signaturelen == 0) return -1; - switch(key->type){ + switch (key->type) { case KEY_DSA: return ssh_dss_verify(key, signature, signaturelen, data, datalen); break; diff --git a/openssh/key.h b/openssh/key.h index 00eebb7..a225773 100644 --- a/openssh/key.h +++ b/openssh/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.17 2001/09/17 19:27:15 stevesk Exp $ */ +/* $OpenBSD: key.h,v 1.18 2002/02/24 19:14:59 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -74,7 +74,7 @@ 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 **, int *, u_char *, int); -int key_verify(Key *, u_char *, int, u_char *, int); +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 diff --git a/openssh/log.c b/openssh/log.c index 39bc8b5..c88f632 100644 --- a/openssh/log.c +++ b/openssh/log.c @@ -34,7 +34,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: log.c,v 1.18 2001/06/26 17:27:23 markus Exp $"); +RCSID("$OpenBSD: log.c,v 1.22 2002/02/22 12:20:34 markus Exp $"); #include "log.h" #include "xmalloc.h" @@ -68,7 +68,7 @@ static struct { { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, - { NULL, 0 } + { NULL, SYSLOG_FACILITY_NOT_SET } }; static struct { @@ -85,11 +85,9 @@ static struct { { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, - { NULL, 0 } + { NULL, SYSLOG_LEVEL_NOT_SET } }; -static void do_log(LogLevel level, const char *fmt, va_list args); - SyslogFacility log_facility_number(char *name) { @@ -98,7 +96,7 @@ log_facility_number(char *name) 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 @@ -109,18 +107,7 @@ log_level_number(char *name) 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. */ @@ -242,7 +229,7 @@ fatal_cleanup(void) 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); @@ -328,7 +315,7 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) #define MSGBUFSIZ 1024 -static void +void do_log(LogLevel level, const char *fmt, va_list args) { char msgbuf[MSGBUFSIZ]; diff --git a/openssh/log.h b/openssh/log.h index 23451f7..42a9a6e 100644 --- a/openssh/log.h +++ b/openssh/log.h @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.4 2001/06/26 17:27:24 markus Exp $ */ +/* $OpenBSD: log.h,v 1.6 2002/02/22 12:20:34 markus Exp $ */ /* * Author: Tatu Ylonen @@ -32,7 +32,8 @@ typedef enum { SYSLOG_FACILITY_LOCAL4, SYSLOG_FACILITY_LOCAL5, SYSLOG_FACILITY_LOCAL6, - SYSLOG_FACILITY_LOCAL7 + SYSLOG_FACILITY_LOCAL7, + SYSLOG_FACILITY_NOT_SET = -1, } SyslogFacility; typedef enum { @@ -43,7 +44,8 @@ typedef enum { SYSLOG_LEVEL_VERBOSE, SYSLOG_LEVEL_DEBUG1, SYSLOG_LEVEL_DEBUG2, - SYSLOG_LEVEL_DEBUG3 + SYSLOG_LEVEL_DEBUG3, + SYSLOG_LEVEL_NOT_SET = -1, } LogLevel; void log_init(char *, LogLevel, SyslogFacility, int); @@ -63,4 +65,6 @@ void fatal_cleanup(void); void fatal_add_cleanup(void (*) (void *), void *); void fatal_remove_cleanup(void (*) (void *), void *); +void do_log(LogLevel, const char *, va_list); + #endif diff --git a/openssh/loginrec.c b/openssh/loginrec.c index 87c336d..1805f3e 100644 --- a/openssh/loginrec.c +++ b/openssh/loginrec.c @@ -701,6 +701,8 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) 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; @@ -710,8 +712,6 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) * for logouts. */ - /* strncpy(): Don't necessarily want null termination */ - strncpy(utx->ut_name, li->username, MIN_SIZEOF(utx->ut_name, li->username)); # ifdef HAVE_HOST_IN_UTMPX strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); # endif @@ -942,9 +942,7 @@ utmpx_perform_logout(struct logininfo *li) { struct utmpx utx; - memset(&utx, '\0', sizeof(utx)); - set_utmpx_time(li, &utx); - line_stripname(utx.ut_line, li->line, sizeof(utx.ut_line)); + construct_utmpx(li, &utx); # ifdef HAVE_ID_IN_UTMPX line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id)); # endif diff --git a/openssh/mac.c b/openssh/mac.c index e8b4267..b250af2 100644 --- a/openssh/mac.c +++ b/openssh/mac.c @@ -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.4 2002/01/25 22:07:40 markus Exp $"); #include @@ -56,7 +56,7 @@ mac_init(Mac *mac, char *name) 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 @@ mac_valid(const char *names) 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); diff --git a/openssh/match.c b/openssh/match.c index 188b9a4..3ddb627 100644 --- a/openssh/match.c +++ b/openssh/match.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: match.c,v 1.14 2001/06/27 04:48:53 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 @@ match_pattern(const char *s, const char *pattern) } /* - * 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 @@ match_hostname(const char *host, const char *pattern, u_int len) * 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 @@ match_hostname(const char *host, const char *pattern, u_int len) /* 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,6 +164,18 @@ match_hostname(const char *host, const char *pattern, u_int len) 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); +} + /* * 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. @@ -212,7 +226,7 @@ match_user(const char *user, const char *host, const char *ipaddr, * Returns first item from client-list that is also supported by server-list, * caller must xfree() returned string. */ -#define MAX_PROP 20 +#define MAX_PROP 40 #define SEP "," char * match_list(const char *client, const char *server, u_int *next) @@ -225,7 +239,7 @@ match_list(const char *client, const char *server, u_int *next) 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 @@ -234,7 +248,7 @@ match_list(const char *client, const char *server, u_int *next) 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); diff --git a/openssh/match.h b/openssh/match.h index f05fe9b..a0764e0 100644 --- a/openssh/match.h +++ b/openssh/match.h @@ -1,4 +1,4 @@ -/* $OpenBSD: match.h,v 1.9 2001/06/26 06:32:56 itojun Exp $ */ +/* $OpenBSD: match.h,v 1.12 2002/03/01 13:12:10 markus Exp $ */ /* * Author: Tatu Ylonen @@ -14,8 +14,9 @@ #ifndef MATCH_H #define MATCH_H -int match_pattern(const char *, const char *); -int match_hostname(const char *, const char *, u_int); +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 *); diff --git a/openssh/misc.c b/openssh/misc.c index 620121f..e9fcef6 100644 --- a/openssh/misc.c +++ b/openssh/misc.c @@ -1,5 +1,3 @@ -/* $OpenBSD: misc.c,v 1.12 2001/06/26 17:27:24 markus Exp $ */ - /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -25,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: misc.c,v 1.12 2001/06/26 17:27:24 markus Exp $"); +RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $"); #include "misc.h" #include "log.h" @@ -37,7 +35,7 @@ chop(char *s) { char *t = s; while (*t) { - if(*t == '\n' || *t == '\r') { + if (*t == '\n' || *t == '\r') { *t = '\0'; return s; } @@ -65,9 +63,8 @@ set_nonblock(int fd) 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 @@ -87,9 +84,30 @@ unset_nonblock(int fd) debug("fd %d clearing 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)); +} + +/* 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. */ @@ -298,7 +316,7 @@ addargs(arglist *args, char *fmt, ...) if (args->list == NULL) { args->nalloc = 32; args->num = 0; - } else if (args->num+2 >= args->nalloc) + } else if (args->num+2 >= args->nalloc) args->nalloc *= 2; args->list = xrealloc(args->list, args->nalloc * sizeof(char *)); diff --git a/openssh/misc.h b/openssh/misc.h index fc56452..668fd60 100644 --- a/openssh/misc.h +++ b/openssh/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.10 2001/06/26 17:27:24 markus Exp $ */ +/* $OpenBSD: misc.h,v 1.11 2002/01/24 21:09:25 stevesk Exp $ */ /* * Author: Tatu Ylonen @@ -16,6 +16,7 @@ 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 *); diff --git a/openssh/mpaux.h b/openssh/mpaux.h index 082b7fd..2a312f5 100644 --- a/openssh/mpaux.h +++ b/openssh/mpaux.h @@ -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,8 +14,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: mpaux.h,v 1.11 2001/06/26 17:27:24 markus Exp $"); */ - #ifndef MPAUX_H #define MPAUX_H diff --git a/openssh/myproposal.h b/openssh/myproposal.h index 4a9a363..1caf04a 100644 --- a/openssh/myproposal.h +++ b/openssh/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.12 2001/03/05 15:56:16 deraadt Exp $ */ +/* $OpenBSD: myproposal.h,v 1.13 2002/01/21 22:30:12 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -27,9 +27,7 @@ #define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" #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" #define KEX_DEFAULT_MAC \ "hmac-md5,hmac-sha1,hmac-ripemd160," \ "hmac-ripemd160@openssh.com," \ diff --git a/openssh/nchan.c b/openssh/nchan.c index 2680f0a..fc8e7f1 100644 --- a/openssh/nchan.c +++ b/openssh/nchan.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2000, 2001 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,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: nchan.c,v 1.32 2001/10/10 22:18:47 markus Exp $"); +RCSID("$OpenBSD: nchan.c,v 1.44 2002/01/21 23:27:10 markus Exp $"); #include "ssh1.h" #include "ssh2.h" @@ -63,14 +63,6 @@ RCSID("$OpenBSD: nchan.c,v 1.32 2001/10/10 22:18:47 markus Exp $"); /* * 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 */ @@ -83,6 +75,28 @@ static void chan_send_eof2(Channel *); 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 */ @@ -93,20 +107,17 @@ chan_rcvd_oclose1(Channel *c) 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: rcvd_oclose for istate %d", @@ -114,21 +125,14 @@ chan_rcvd_oclose1(Channel *c) 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 0 - if (buffer_len(&c->input) == 0) { - debug("channel %d: input: no drain shortcut", c->self); - chan_ibuf_empty(c); - } -#endif + chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); break; default: error("channel %d: chan_read_failed for istate %d", @@ -136,8 +140,8 @@ chan_read_failed_12(Channel *c) 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)) { @@ -147,9 +151,14 @@ chan_ibuf_empty1(Channel *c) } 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: chan_ibuf_empty for istate %d", @@ -161,37 +170,12 @@ static void 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: non-open: 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: non-open: 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: rcvd_ieof for ostate %d", @@ -205,14 +189,14 @@ chan_write_failed1(Channel *c) 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: chan_write_failed for ostate %d", @@ -220,8 +204,8 @@ chan_write_failed1(Channel *c) 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)) { @@ -231,9 +215,10 @@ chan_obuf_empty1(Channel *c) } 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: obuf_empty for ostate %d", @@ -265,15 +250,14 @@ chan_send_oclose1(Channel *c) 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: cannot send oclose for ostate %d", - c->self, c->ostate); + c->self, c->ostate); break; } } @@ -282,7 +266,7 @@ chan_send_oclose1(Channel *c) * 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) @@ -290,8 +274,8 @@ chan_rcvd_oclose2(Channel *c) 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) { @@ -300,52 +284,26 @@ chan_rcvd_oclose2(Channel *c) * 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; + 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: 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: 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; - } + if (c->ostate == CHAN_OUTPUT_OPEN) + chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); } static void chan_write_failed2(Channel *c) @@ -353,14 +311,9 @@ chan_write_failed2(Channel *c) 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: chan_write_failed for ostate %d", @@ -369,27 +322,6 @@ chan_write_failed2(Channel *c) } } static void -chan_obuf_empty2(Channel *c) -{ - debug("channel %d: obuf empty", c->self); - if (buffer_len(&c->output)) { - 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_shutdown_write(c); - c->ostate = CHAN_OUTPUT_CLOSED; - break; - default: - error("channel %d: chan_obuf_empty for ostate %d", - c->self, c->ostate); - break; - } -} -static void chan_send_eof2(Channel *c) { debug("channel %d: send eof", c->self); @@ -425,6 +357,34 @@ chan_send_close2(Channel *c) /* 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) + 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) { @@ -458,7 +418,7 @@ chan_is_dead(Channel *c, int send) 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"); + "read": "write"); } else { if (!(c->flags & CHAN_CLOSE_SENT)) { if (send) { @@ -481,42 +441,11 @@ chan_is_dead(Channel *c, int send) 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; - } -} - /* 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 */ diff --git a/openssh/openbsd-compat/Makefile.in b/openssh/openbsd-compat/Makefile.in index 31f9ea9..df57111 100644 --- a/openssh/openbsd-compat/Makefile.in +++ b/openssh/openbsd-compat/Makefile.in @@ -20,6 +20,8 @@ OPENBSD=base64.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getop 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 $< @@ -27,9 +29,10 @@ all: libopenbsd-compat.a $(COMPAT): ../config.h $(OPENBSD): ../config.h +$(PORTS): ../config.h -libopenbsd-compat.a: $(COMPAT) $(OPENBSD) - $(AR) rv $@ $(COMPAT) $(OPENBSD) +libopenbsd-compat.a: $(COMPAT) $(OPENBSD) $(PORTS) + $(AR) rv $@ $(COMPAT) $(OPENBSD) $(PORTS) $(RANLIB) $@ clean: diff --git a/openssh/openbsd-compat/base64.h b/openssh/openbsd-compat/base64.h index 0ebfdd3..a49bea4 100644 --- a/openssh/openbsd-compat/base64.h +++ b/openssh/openbsd-compat/base64.h @@ -15,4 +15,4 @@ int b64_pton(char const *src, u_char *target, size_t targsize); # define __b64_pton b64_pton #endif /* HAVE___B64_NTOP */ -#endif /* _BSD_BINRESVPORT_H */ +#endif /* _BSD_BASE64_H */ diff --git a/openssh/openbsd-compat/bsd-cygwin_util.c b/openssh/openbsd-compat/bsd-cygwin_util.c index f513331..f56ad7c 100644 --- a/openssh/openbsd-compat/bsd-cygwin_util.c +++ b/openssh/openbsd-compat/bsd-cygwin_util.c @@ -58,7 +58,7 @@ int binary_pipe(int fd[2]) return ret; } -int check_nt_auth(int pwd_authenticated, uid_t uid) +int check_nt_auth(int pwd_authenticated, struct passwd *pw) { /* * The only authentication which is able to change the user @@ -73,6 +73,8 @@ int check_nt_auth(int pwd_authenticated, uid_t uid) */ static int has_create_token = -1; + if (pw == NULL) + return 0; if (is_winnt) { if (has_create_token < 0) { struct utsname uts; @@ -90,7 +92,7 @@ int check_nt_auth(int pwd_authenticated, uid_t uid) } } if (has_create_token < 1 && - !pwd_authenticated && geteuid() != uid) + !pwd_authenticated && geteuid() != pw->pw_uid) return 0; } return 1; @@ -139,4 +141,26 @@ int check_ntsec(const char *filename) 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 */ diff --git a/openssh/openbsd-compat/bsd-cygwin_util.h b/openssh/openbsd-compat/bsd-cygwin_util.h index 8bd5fad..a87aeee 100644 --- a/openssh/openbsd-compat/bsd-cygwin_util.h +++ b/openssh/openbsd-compat/bsd-cygwin_util.h @@ -24,8 +24,9 @@ int binary_open(const char *filename, int flags, ...); int binary_pipe(int fd[2]); -int check_nt_auth(int pwd_authenticated, uid_t uid); +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 diff --git a/openssh/openbsd-compat/daemon.c b/openssh/openbsd-compat/daemon.c index f704a90..7d23b24 100644 --- a/openssh/openbsd-compat/daemon.c +++ b/openssh/openbsd-compat/daemon.c @@ -49,6 +49,9 @@ daemon(nochdir, noclose) case -1: return (-1); case 0: +#ifdef HAVE_CYGWIN + register_9x_service(); +#endif break; default: #ifdef HAVE_CYGWIN diff --git a/openssh/openbsd-compat/dirname.c b/openssh/openbsd-compat/dirname.c index a76a1dc..391b2dd 100644 --- a/openssh/openbsd-compat/dirname.c +++ b/openssh/openbsd-compat/dirname.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dirname.c,v 1.5 2001/06/27 00:58:54 lebel Exp $ */ +/* $OpenBSD: dirname.c,v 1.6 2001/06/28 04:27:19 pjanzen Exp $ */ /* * Copyright (c) 1997 Todd C. Miller @@ -31,7 +31,7 @@ #ifndef HAVE_DIRNAME #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: dirname.c,v 1.5 2001/06/27 00:58:54 lebel Exp $"; +static char rcsid[] = "$OpenBSD: dirname.c,v 1.6 2001/06/28 04:27:19 pjanzen Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -70,7 +70,7 @@ dirname(path) } while (endp > path && *endp == '/'); } - if (endp - path + 1 > sizeof(bname)) { + if (endp - path + 2 > sizeof(bname)) { errno = ENAMETOOLONG; return(NULL); } diff --git a/openssh/openbsd-compat/fake-queue.h b/openssh/openbsd-compat/fake-queue.h index 269af41..c85bb24 100644 --- a/openssh/openbsd-compat/fake-queue.h +++ b/openssh/openbsd-compat/fake-queue.h @@ -1,4 +1,4 @@ -/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */ +/* $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 $ */ /* @@ -136,6 +136,19 @@ struct { \ (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. */ diff --git a/openssh/openbsd-compat/mktemp.c b/openssh/openbsd-compat/mktemp.c index 9ed1bc8..d69dc5c 100644 --- a/openssh/openbsd-compat/mktemp.c +++ b/openssh/openbsd-compat/mktemp.c @@ -39,7 +39,7 @@ #ifndef HAVE_MKDTEMP #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp $"; +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 @@ -84,7 +84,8 @@ _gettemp(path, doopen, domkdir, slen) { register char *start, *trv, *suffp; struct stat sbuf; - int pid, rval; + int rval; + pid_t pid; if (doopen && domkdir) { errno = EINVAL; diff --git a/openssh/openbsd-compat/openbsd-compat.h b/openssh/openbsd-compat/openbsd-compat.h index 845d98f..551bdc9 100644 --- a/openssh/openbsd-compat/openbsd-compat.h +++ b/openssh/openbsd-compat/openbsd-compat.h @@ -40,5 +40,7 @@ /* Routines for a single OS platform */ #include "bsd-cray.h" +#include "port-irix.h" +#include "port-aix.h" #endif /* _OPENBSD_H */ diff --git a/openssh/openbsd-compat/port-aix.c b/openssh/openbsd-compat/port-aix.c new file mode 100644 index 0000000..31697d7 --- /dev/null +++ b/openssh/openbsd-compat/port-aix.c @@ -0,0 +1,126 @@ +#include "includes.h" + +#ifdef _AIX + +#ifdef HAVE_USERSEC_H +#include +#endif /* HAVE_USERSEC_H */ + +#include +#include <../xmalloc.h> + +/* AIX limits */ +#if defined(HAVE_GETUSERATTR) && !defined(S_UFSIZE_HARD) && defined(S_UFSIZE) +# define S_UFSIZE_HARD S_UFSIZE "_hard" +# define S_UCPU_HARD S_UCPU "_hard" +# define S_UDATA_HARD S_UDATA "_hard" +# define S_USTACK_HARD S_USTACK "_hard" +# define S_URSS_HARD S_URSS "_hard" +# define S_UCORE_HARD S_UCORE "_hard" +# define S_UNOFILE_HARD S_UNOFILE "_hard" +#endif + +#if defined(HAVE_GETUSERATTR) +/* + * AIX-specific login initialisation + */ +void +set_limit(char *user, char *soft, char *hard, int resource, int mult) +{ + struct rlimit rlim; + int slim, hlim; + + getrlimit(resource, &rlim); + + slim = 0; + if (getuserattr(user, soft, &slim, SEC_INT) != -1) { + if (slim < 0) { + rlim.rlim_cur = RLIM_INFINITY; + } else if (slim != 0) { + /* See the wackiness below */ + if (rlim.rlim_cur == slim * mult) + slim = 0; + else + rlim.rlim_cur = slim * mult; + } + } + hlim = 0; + if (getuserattr(user, hard, &hlim, SEC_INT) != -1) { + if (hlim < 0) { + rlim.rlim_max = RLIM_INFINITY; + } else if (hlim != 0) { + rlim.rlim_max = hlim * mult; + } + } + + /* + * XXX For cpu and fsize the soft limit is set to the hard limit + * if the hard limit is left at its default value and the soft limit + * is changed from its default value, either by requesting it + * (slim == 0) or by setting it to the current default. At least + * that's how rlogind does it. If you're confused you're not alone. + * Bug or feature? AIX 4.3.1.2 + */ + if ((!strcmp(soft, "fsize") || !strcmp(soft, "cpu")) + && hlim == 0 && slim != 0) + rlim.rlim_max = rlim.rlim_cur; + /* A specified hard limit limits the soft limit */ + else if (hlim > 0 && rlim.rlim_cur > rlim.rlim_max) + rlim.rlim_cur = rlim.rlim_max; + /* A soft limit can increase a hard limit */ + else if (rlim.rlim_cur > rlim.rlim_max) + rlim.rlim_max = rlim.rlim_cur; + + if (setrlimit(resource, &rlim) != 0) + error("setrlimit(%.10s) failed: %.100s", soft, strerror(errno)); +} + +void +set_limits_from_userattr(char *user) +{ + int mask; + char buf[16]; + + set_limit(user, S_UFSIZE, S_UFSIZE_HARD, RLIMIT_FSIZE, 512); + set_limit(user, S_UCPU, S_UCPU_HARD, RLIMIT_CPU, 1); + set_limit(user, S_UDATA, S_UDATA_HARD, RLIMIT_DATA, 512); + set_limit(user, S_USTACK, S_USTACK_HARD, RLIMIT_STACK, 512); + set_limit(user, S_URSS, S_URSS_HARD, RLIMIT_RSS, 512); + set_limit(user, S_UCORE, S_UCORE_HARD, RLIMIT_CORE, 512); +#if defined(S_UNOFILE) + set_limit(user, S_UNOFILE, S_UNOFILE_HARD, RLIMIT_NOFILE, 1); +#endif + + if (getuserattr(user, S_UMASK, &mask, SEC_INT) != -1) { + /* Convert decimal to octal */ + (void) snprintf(buf, sizeof(buf), "%d", mask); + if (sscanf(buf, "%o", &mask) == 1) + umask(mask); + } +} +#endif /* defined(HAVE_GETUSERATTR) */ + +/* + * 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 */ + diff --git a/openssh/openbsd-compat/port-aix.h b/openssh/openbsd-compat/port-aix.h new file mode 100644 index 0000000..29d2ee6 --- /dev/null +++ b/openssh/openbsd-compat/port-aix.h @@ -0,0 +1,10 @@ +#ifdef _AIX + +#ifdef HAVE_GETUSERATTR +void set_limit(char *user, char *soft, char *hard, int resource, int mult); +void set_limits_from_userattr(char *user); +#endif /* HAVE_GETUSERATTR */ + +void aix_usrinfo(struct passwd *pw, char *tty, int ttyfd); + +#endif /* _AIX */ diff --git a/openssh/openbsd-compat/port-irix.c b/openssh/openbsd-compat/port-irix.c new file mode 100644 index 0000000..a63ec42 --- /dev/null +++ b/openssh/openbsd-compat/port-irix.c @@ -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) */ diff --git a/openssh/openbsd-compat/port-irix.h b/openssh/openbsd-compat/port-irix.h new file mode 100644 index 0000000..2dd3c2e --- /dev/null +++ b/openssh/openbsd-compat/port-irix.h @@ -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) */ diff --git a/openssh/openbsd-compat/readpassphrase.c b/openssh/openbsd-compat/readpassphrase.c index fdef158..7687710 100644 --- a/openssh/openbsd-compat/readpassphrase.c +++ b/openssh/openbsd-compat/readpassphrase.c @@ -1,3 +1,5 @@ +/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $ */ + /* * Copyright (c) 2000 Todd C. Miller * All rights reserved. @@ -26,7 +28,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.5 2001/06/27 13:23:30 djm Exp $"; +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" @@ -47,20 +49,19 @@ static char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.5 2001/06/27 13:23:30 djm # define _POSIX_VDISABLE VDISABLE #endif +static volatile sig_atomic_t signo; + +static void handler(int); + char * -readpassphrase(prompt, buf, bufsiz, flags) - const char *prompt; - char *buf; - size_t bufsiz; - int flags; +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) { - struct termios term; + ssize_t nr; + int input, output, save_errno; char ch, *p, *end; -#ifdef _POSIX_VDISABLE - u_char status; -#endif - int echo, input, output; - sigset_t oset, nset; + 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) { @@ -68,6 +69,7 @@ readpassphrase(prompt, buf, bufsiz, flags) 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. @@ -82,44 +84,39 @@ readpassphrase(prompt, buf, bufsiz, flags) } /* - * We block SIGINT and SIGTSTP so the terminal is not left - * in an inconsistent state (ie: no echo). It would probably - * be better to simply catch these though. + * 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(&nset); - sigaddset(&nset, SIGINT); - sigaddset(&nset, SIGTSTP); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); + 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. */ - echo = 0; -#ifdef _POSIX_VDISABLE - status = _POSIX_VDISABLE; -#endif - if (tcgetattr(input, &term) == 0) { - if (!(flags & RPP_ECHO_ON) && (term.c_lflag & ECHO)) { - echo = 1; - term.c_lflag &= ~ECHO; - } + 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) { - status = term.c_cc[VSTATUS]; + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) term.c_cc[VSTATUS] = _POSIX_VDISABLE; - } #endif (void)tcsetattr(input, _T_FLUSH, &term); - } - if (!(flags & RPP_ECHO_ON)) { - if (tcgetattr(input, &term) == 0 && (term.c_lflag & ECHO)) { - echo = 1; - term.c_lflag &= ~ECHO; - (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; read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) { + for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { if (p < end) { if ((flags & RPP_SEVENBIT)) ch &= 0x7f; @@ -133,35 +130,55 @@ readpassphrase(prompt, buf, bufsiz, flags) } } *p = '\0'; -#ifdef _POSIX_VDISABLE - if (echo || status != _POSIX_VDISABLE) { -#else - if (echo) { -#endif - if (echo) { - (void)write(output, "\n", 1); - term.c_lflag |= ECHO; - } -#ifdef VSTATUS - if (status != _POSIX_VDISABLE) - term.c_cc[VSTATUS] = status; -#endif - (void)tcsetattr(input, _T_FLUSH, &term); - } - (void)sigprocmask(SIG_SETMASK, &oset, NULL); + 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); - return(buf); + + /* + * 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); } #endif /* HAVE_READPASSPHRASE */ - + #if 0 char * -getpass(prompt) - const char *prompt; +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; +} diff --git a/openssh/openbsd-compat/realpath.c b/openssh/openbsd-compat/realpath.c index ec801d4..b4a05db 100644 --- a/openssh/openbsd-compat/realpath.c +++ b/openssh/openbsd-compat/realpath.c @@ -32,7 +32,7 @@ #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: realpath.c,v 1.5 2001/06/27 00:58:56 lebel Exp $"; +static char *rcsid = "$OpenBSD: realpath.c,v 1.6 2002/01/12 16:24:35 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -74,6 +74,10 @@ realpath(const char *path, char *resolved) } 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. @@ -102,7 +106,7 @@ loop: p = resolved; /* Deal with the last component. */ - if (lstat(p, &sb) == 0) { + if (*p != '\0' && lstat(p, &sb) == 0) { if (S_ISLNK(sb.st_mode)) { if (++symlinks > MAXSYMLINKS) { serrno = ELOOP; diff --git a/openssh/openbsd-compat/setenv.c b/openssh/openbsd-compat/setenv.c index ac9670b..6c2d5cd 100644 --- a/openssh/openbsd-compat/setenv.c +++ b/openssh/openbsd-compat/setenv.c @@ -35,7 +35,7 @@ #ifndef HAVE_SETENV #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: setenv.c,v 1.3 1998/02/02 22:44:53 millert Exp $"; +static char *rcsid = "$OpenBSD: setenv.c,v 1.4 2001/07/09 06:57:45 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -101,7 +101,8 @@ setenv(name, value, rewrite) if (!rewrite) return (0); if (strlen(C) >= l_value) { /* old larger; copy over */ - while ((*C++ = *value++)); + while ((*C++ = *value++)) + ; return (0); } } else { /* create new slot */ diff --git a/openssh/openbsd-compat/setproctitle.c b/openssh/openbsd-compat/setproctitle.c index 38eca9a..e165dd1 100644 --- a/openssh/openbsd-compat/setproctitle.c +++ b/openssh/openbsd-compat/setproctitle.c @@ -35,7 +35,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: setproctitle.c,v 1.7 1999/02/25 22:10:12 art Exp $"; +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" diff --git a/openssh/packet.c b/openssh/packet.c index 7b94169..045d5a1 100644 --- a/openssh/packet.c +++ b/openssh/packet.c @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: packet.c,v 1.72 2001/11/10 13:37:20 markus Exp $"); +RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $"); #include "xmalloc.h" #include "buffer.h" @@ -59,6 +59,7 @@ RCSID("$OpenBSD: packet.c,v 1.72 2001/11/10 13:37:20 markus Exp $"); #include "mac.h" #include "log.h" #include "canohost.h" +#include "misc.h" #ifdef PACKET_DEBUG #define DBG(x) x @@ -130,8 +131,8 @@ packet_set_connection(int fd_in, int fd_out) fatal("packet_set_connection: cannot load cipher 'none'"); connection_in = fd_in; connection_out = fd_out; - 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; @@ -147,7 +148,7 @@ packet_set_connection(int fd_in, int fd_out) /* 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; @@ -173,7 +174,7 @@ packet_connection_is_on_socket() /* 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); @@ -189,7 +190,7 @@ packet_connection_is_ipv4() /* 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) @@ -204,7 +205,7 @@ packet_set_nonblocking() /* Returns the socket used for reading. */ int -packet_get_connection_in() +packet_get_connection_in(void) { return connection_in; } @@ -212,7 +213,7 @@ packet_get_connection_in() /* Returns the descriptor used for writing. */ int -packet_get_connection_out() +packet_get_connection_out(void) { return connection_out; } @@ -220,7 +221,7 @@ packet_get_connection_out() /* Closes the connection and clears and frees internal data structures. */ void -packet_close() +packet_close(void) { if (!initialized) return; @@ -240,6 +241,8 @@ packet_close() buffer_free(&compression_buffer); buffer_compress_uninit(); } + cipher_cleanup(&send_context); + cipher_cleanup(&receive_context); } /* Sets remote side protocol flags. */ @@ -253,7 +256,7 @@ packet_set_protocol_flags(u_int protocol_flags) /* 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; } @@ -297,8 +300,8 @@ packet_set_encryption_key(const u_char *key, u_int keylen, 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); + cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); + cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); } /* Start constructing a packet to send. */ @@ -329,7 +332,7 @@ packet_put_int(u_int value) buffer_put_int(&outgoing_packet, value); } 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); } @@ -339,7 +342,7 @@ packet_put_cstring(const char *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); } @@ -362,7 +365,7 @@ packet_put_bignum2(BIGNUM * value) 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; @@ -380,14 +383,14 @@ packet_send1(void) 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 (send_context.cipher->number != SSH_CIPHER_NONE) { + if (!send_context.plaintext) { cp = buffer_ptr(&outgoing_packet); for (i = 0; i < padding; i++) { if (i % 4 == 0) @@ -399,7 +402,7 @@ packet_send1(void) 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); @@ -412,9 +415,9 @@ packet_send1(void) /* Append to output. */ PUT_32BIT(buf, len); buffer_append(&output, buf, 4); - buffer_append_space(&output, &cp, buffer_len(&outgoing_packet)); - cipher_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: "); @@ -437,14 +440,20 @@ set_newkeys(int mode) 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; @@ -466,10 +475,10 @@ set_newkeys(int mode) 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); + 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) @@ -487,9 +496,8 @@ static void packet_send2(void) { static u_int32_t seqnr = 0; - u_char type, *ucp, *macbuf = NULL; + u_char type, *cp, *macbuf = NULL; u_char padlen, pad; - char *cp; u_int packet_length = 0; u_int i, len; u_int32_t rand = 0; @@ -503,10 +511,10 @@ packet_send2(void) 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; - ucp = (u_char *) buffer_ptr(&outgoing_packet); - type = ucp[5]; + cp = buffer_ptr(&outgoing_packet); + type = cp[5]; #ifdef PACKET_DEBUG fprintf(stderr, "plain: "); @@ -546,8 +554,8 @@ packet_send2(void) padlen += pad; extra_pad = 0; } - buffer_append_space(&outgoing_packet, &cp, padlen); - if (enc && enc->cipher->number != SSH_CIPHER_NONE) { + cp = buffer_append_space(&outgoing_packet, padlen); + if (enc && !send_context.plaintext) { /* random padding */ for (i = 0; i < padlen; i++) { if (i % 4 == 0) @@ -561,21 +569,21 @@ packet_send2(void) } /* packet_length includes payload, padding and padding length field */ packet_length = buffer_len(&outgoing_packet) - 4; - ucp = (u_char *)buffer_ptr(&outgoing_packet); - PUT_32BIT(ucp, packet_length); - ucp[4] = padlen; + cp = buffer_ptr(&outgoing_packet); + PUT_32BIT(cp, packet_length); + 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), + buffer_ptr(&outgoing_packet), buffer_len(&outgoing_packet)); DBG(debug("done calc MAC out #%d", seqnr)); } /* encrypt packet and append to output buffer. */ - buffer_append_space(&output, &cp, buffer_len(&outgoing_packet)); - cipher_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) @@ -594,7 +602,7 @@ packet_send2(void) } void -packet_send() +packet_send(void) { if (compat20) packet_send2(); @@ -610,7 +618,7 @@ packet_send() */ int -packet_read(int *payload_len_ptr) +packet_read_seqnr(u_int32_t *seqnr_p) { int type, len; fd_set *setp; @@ -626,13 +634,13 @@ packet_read(int *payload_len_ptr) /* 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); + 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); @@ -665,17 +673,23 @@ packet_read(int *payload_len_ptr) /* 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); @@ -688,28 +702,21 @@ packet_read_expect(int *payload_len_ptr, int expected_type) * 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 */ static int -packet_read_poll1(int *payload_len_ptr) +packet_read_poll1(void) { u_int len, padded_len; - u_char *ucp, type; - char *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; @@ -728,14 +735,14 @@ packet_read_poll1(int *payload_len_ptr) * (C)1998 CORE-SDI, Buenos Aires Argentina * Ariel Futoransky(futo@core-sdi.com) */ - if (receive_context.cipher->number != SSH_CIPHER_NONE && + 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); - cipher_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); @@ -745,7 +752,7 @@ packet_read_poll1(int *payload_len_ptr) #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. */ @@ -753,11 +760,11 @@ packet_read_poll1(int *payload_len_ptr) /* 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); @@ -770,18 +777,16 @@ packet_read_poll1(int *payload_len_ptr) buffer_len(&compression_buffer)); } type = buffer_get_char(&incoming_packet); - *payload_len_ptr = buffer_len(&incoming_packet); return type; } static int -packet_read_poll2(int *payload_len_ptr) +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 *macbuf, *ucp, type; - char *cp; + u_char *macbuf, *cp, type; int maclen, block_size; Enc *enc = NULL; Mac *mac = NULL; @@ -793,7 +798,7 @@ packet_read_poll2(int *payload_len_ptr) 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) { /* @@ -803,11 +808,11 @@ packet_read_poll2(int *payload_len_ptr) if (buffer_len(&input) < block_size) return SSH_MSG_NONE; buffer_clear(&incoming_packet); - buffer_append_space(&incoming_packet, &cp, block_size); - cipher_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); @@ -832,8 +837,8 @@ packet_read_poll2(int *payload_len_ptr) fprintf(stderr, "read_poll enc/full: "); buffer_dump(&input); #endif - buffer_append_space(&incoming_packet, &cp, need); - cipher_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, @@ -841,19 +846,21 @@ packet_read_poll2(int *payload_len_ptr) */ if (mac && mac->enabled) { macbuf = mac_compute(mac, seqnr, - (u_char *) buffer_ptr(&incoming_packet), + 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)); buffer_consume(&input, mac->mac_len); } + if (seqnr_p != NULL) + *seqnr_p = seqnr; if (++seqnr == 0) log("incoming seqnr wraps around"); /* get padlen */ - cp = buffer_ptr(&incoming_packet) + 4; - padlen = (u_char) *cp; + 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); @@ -878,7 +885,6 @@ packet_read_poll2(int *payload_len_ptr) type = buffer_get_char(&incoming_packet); if (type == SSH2_MSG_NEWKEYS) set_newkeys(MODE_IN); - *payload_len_ptr = buffer_len(&incoming_packet); #ifdef PACKET_DEBUG fprintf(stderr, "read/plain[%d]:\r\n", type); buffer_dump(&incoming_packet); @@ -889,18 +895,18 @@ packet_read_poll2(int *payload_len_ptr) } int -packet_read_poll(int *payload_len_ptr) +packet_read_poll_seqnr(u_int32_t *seqnr_p) { - int reason; + int reason, seqnr; u_char type; char *msg; for (;;) { if (compat20) { - type = packet_read_poll2(payload_len_ptr); + 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: @@ -919,13 +925,17 @@ packet_read_poll(int *payload_len_ptr) xfree(msg); fatal_cleanup(); break; + case SSH2_MSG_UNIMPLEMENTED: + seqnr = packet_get_int(); + debug("Received SSH2_MSG_UNIMPLEMENTED for %d", seqnr); + break; default: return type; break; } } else { - type = packet_read_poll1(payload_len_ptr); - switch(type) { + type = packet_read_poll1(); + switch (type) { case SSH_MSG_IGNORE: break; case SSH_MSG_DEBUG: @@ -950,6 +960,12 @@ packet_read_poll(int *payload_len_ptr) } } +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. @@ -964,7 +980,7 @@ packet_process_incoming(const char *buf, u_int len) /* Returns a character from the packet. */ u_int -packet_get_char() +packet_get_char(void) { char ch; buffer_get(&incoming_packet, &ch, 1); @@ -974,7 +990,7 @@ packet_get_char() /* Returns an integer from the packet data. */ u_int -packet_get_int() +packet_get_int(void) { return buffer_get_int(&incoming_packet); } @@ -985,18 +1001,18 @@ packet_get_int() */ 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); @@ -1018,7 +1034,7 @@ packet_remaining(void) * 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); @@ -1111,7 +1127,7 @@ packet_disconnect(const char *fmt,...) /* 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) { @@ -1132,7 +1148,7 @@ packet_write_poll() */ void -packet_write_wait() +packet_write_wait(void) { fd_set *setp; @@ -1154,7 +1170,7 @@ packet_write_wait() /* 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; } @@ -1162,7 +1178,7 @@ packet_have_data_to_write() /* 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; @@ -1180,7 +1196,6 @@ packet_set_interactive(int interactive) int lowdelay = IPTOS_LOWDELAY; int throughput = IPTOS_THROUGHPUT; #endif - int on = 1; if (called) return; @@ -1203,21 +1218,19 @@ packet_set_interactive(int interactive) #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)); } #endif - if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *) &on, - sizeof(on)) < 0) - error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); + set_nodelay(connection_in); } else if (packet_connection_is_ipv4()) { /* * Set IP options for a non-interactive connection. Use * IPTOS_THROUGHPUT. */ #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &throughput, + if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, sizeof(throughput)) < 0) error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); #endif @@ -1227,7 +1240,7 @@ packet_set_interactive(int interactive) /* Returns true if the current connection is interactive. */ int -packet_is_interactive() +packet_is_interactive(void) { return interactive_mode; } @@ -1277,7 +1290,7 @@ packet_send_ignore(int nbytes) 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); diff --git a/openssh/packet.h b/openssh/packet.h index d547300..d6bf2aa 100644 --- a/openssh/packet.h +++ b/openssh/packet.h @@ -1,3 +1,5 @@ +/* $OpenBSD: packet.h,v 1.33 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". */ -/* RCSID("$OpenBSD: packet.h,v 1.26 2001/11/07 16:03:17 markus Exp $"); */ - #ifndef PACKET_H #define PACKET_H @@ -35,22 +35,24 @@ 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 char *buf, u_int len); +void packet_put_string(const void *buf, u_int len); void packet_put_cstring(const char *str); -void packet_put_raw(const char *buf, u_int len); +void packet_put_raw(const void *buf, u_int len); void packet_send(void); -int packet_read(int *payload_len_ptr); -void packet_read_expect(int *payload_len_ptr, int type); -int packet_read_poll(int *packet_len_ptr); +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, int *length_ptr); -void packet_get_bignum2(BIGNUM * value, int *length_ptr); -char *packet_get_raw(int *length_ptr); -char *packet_get_string(u_int *length_ptr); +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))); @@ -72,17 +74,8 @@ extern int max_packet_size; 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) { \ diff --git a/openssh/pathnames.h b/openssh/pathnames.h index 0470a21..002c313 100644 --- a/openssh/pathnames.h +++ b/openssh/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.9 2001/06/23 02:34:30 markus Exp $ */ +/* $OpenBSD: pathnames.h,v 1.11 2002/02/09 17:37:34 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -12,8 +12,10 @@ * called by a name other than "ssh" or "Secure Shell". */ -#ifndef ETCDIR #define ETCDIR "/etc" + +#ifndef SSHDIR +#define SSHDIR ETCDIR "/ssh" #endif #ifndef _PATH_SSH_PIDDIR @@ -24,22 +26,22 @@ * 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_HOSTFILE SSHDIR "/ssh_known_hosts" /* backward compat for protocol 2 */ -#define _PATH_SSH_SYSTEM_HOSTFILE2 ETCDIR "/ssh_known_hosts2" +#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_MODULI ETCDIR "/moduli" +#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 ETCDIR "/primes" +#define _PATH_DH_PRIMES SSHDIR "/primes" #ifndef _PATH_SSH_PROGRAM #define _PATH_SSH_PROGRAM "/usr/bin/ssh" @@ -102,13 +104,13 @@ * 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" /* @@ -123,6 +125,11 @@ #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" @@ -149,13 +156,3 @@ #ifndef ASKPASS_PROGRAM #define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass" #endif /* ASKPASS_PROGRAM */ - -/* - * Relevant only when using builtin PRNG. - */ -#ifndef SSH_PRNG_SEED_FILE -# define SSH_PRNG_SEED_FILE _PATH_SSH_USER_DIR"/prng_seed" -#endif /* SSH_PRNG_SEED_FILE */ -#ifndef SSH_PRNG_COMMAND_FILE -# define SSH_PRNG_COMMAND_FILE ETCDIR "/ssh_prng_cmds" -#endif /* SSH_PRNG_COMMAND_FILE */ diff --git a/openssh/radix.c b/openssh/radix.c index 26b1ebe..e604357 100644 --- a/openssh/radix.c +++ b/openssh/radix.c @@ -25,7 +25,7 @@ #include "includes.h" #include "uuencode.h" -RCSID("$OpenBSD: radix.c,v 1.16 2001/06/23 15:12:19 itojun Exp $"); +RCSID("$OpenBSD: radix.c,v 1.17 2001/11/19 19:02:16 mpech Exp $"); #ifdef AFS #include @@ -39,7 +39,7 @@ 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); \ + my_u_char *t_cp = (my_u_char *)(cp); \ (s) = (((my_u_short)t_cp[0]) << 8) \ | (((my_u_short)t_cp[1])) \ ; \ @@ -47,7 +47,7 @@ typedef u_short my_u_short; } #define GETLONG(l, cp) { \ - register my_u_char *t_cp = (my_u_char *)(cp); \ + 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) \ @@ -57,16 +57,16 @@ typedef u_short my_u_short; } #define PUTSHORT(s, cp) { \ - register my_u_short t_s = (my_u_short)(s); \ - register my_u_char *t_cp = (my_u_char *)(cp); \ + my_u_short t_s = (my_u_short)(s); \ + my_u_char *t_cp = (my_u_char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ (cp) += 2; \ } #define PUTLONG(l, cp) { \ - register my_u_int32_t t_l = (my_u_int32_t)(l); \ - register my_u_char *t_cp = (my_u_char *)(cp); \ + my_u_int32_t t_l = (my_u_int32_t)(l); \ + my_u_char *t_cp = (my_u_char *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ @@ -75,9 +75,9 @@ typedef u_short my_u_short; } #define GETSTRING(s, p, p_l) { \ - register char *p_targ = (p) + p_l; \ - register char *s_c = (s); \ - register char *p_c = (p); \ + char *p_targ = (p) + p_l; \ + char *s_c = (s); \ + char *p_c = (p); \ while (*p_c && (p_c < p_targ)) { \ *s_c++ = *p_c++; \ } \ diff --git a/openssh/readconf.c b/openssh/readconf.c index 63035b3..7920ac8 100644 --- a/openssh/readconf.c +++ b/openssh/readconf.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.91 2001/10/01 21:51:16 markus Exp $"); +RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $"); #include "ssh.h" #include "xmalloc.h" @@ -115,7 +115,7 @@ typedef enum { oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, - oClearAllForwardings, oNoHostAuthenticationForLocalhost + oClearAllForwardings, oNoHostAuthenticationForLocalhost } OpCodes; /* Textual representations of the tokens. */ @@ -185,9 +185,9 @@ static struct { { "hostkeyalgorithms", oHostKeyAlgorithms }, { "bindaddress", oBindAddress }, { "smartcarddevice", oSmartcardDevice }, - { "clearallforwardings", oClearAllForwardings }, - { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, - { NULL, 0 } + { "clearallforwardings", oClearAllForwardings }, + { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, + { NULL, oBadOption } }; /* @@ -225,7 +225,7 @@ add_remote_forward(Options *options, u_short port, const char *host, 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); @@ -394,7 +394,7 @@ parse_flag: 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; @@ -436,7 +436,7 @@ parse_flag: 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; @@ -536,7 +536,7 @@ parse_int: 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; @@ -547,7 +547,7 @@ parse_int: 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; @@ -558,7 +558,7 @@ parse_int: 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; @@ -569,7 +569,7 @@ parse_int: 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; @@ -582,7 +582,7 @@ parse_int: 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; @@ -591,10 +591,10 @@ parse_int: 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; @@ -670,7 +670,7 @@ parse_int: value = SSH_ESCAPECHAR_NONE; else { fatal("%.200s line %d: Bad escape character.", - filename, linenum); + filename, linenum); /* NOTREACHED */ value = 0; /* Avoid compiler warning. */ } @@ -685,7 +685,7 @@ parse_int: /* 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; } @@ -727,7 +727,7 @@ read_config_file(const char *filename, const char *host, Options *options) fclose(f); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", - filename, bad_options); + filename, bad_options); return 1; } @@ -794,7 +794,7 @@ initialize_options(Options * options) options->num_local_forwards = 0; options->num_remote_forwards = 0; options->clear_forwardings = -1; - options->log_level = (LogLevel) - 1; + options->log_level = SYSLOG_LEVEL_NOT_SET; options->preferred_authentications = NULL; options->bind_address = NULL; options->smartcard_device = NULL; @@ -815,10 +815,8 @@ fill_default_options(Options * options) options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; -#ifdef _PATH_XAUTH if (options->xauth_location == NULL) options->xauth_location = _PATH_XAUTH; -#endif if (options->gateway_ports == -1) options->gateway_ports = 0; if (options->use_privileged_port == -1) @@ -913,7 +911,7 @@ fill_default_options(Options * options) 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); diff --git a/openssh/readconf.h b/openssh/readconf.h index 25ffa46..4fa9040 100644 --- a/openssh/readconf.h +++ b/openssh/readconf.h @@ -1,3 +1,5 @@ +/* $OpenBSD: readconf.h,v 1.42 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". */ -/* RCSID("$OpenBSD: readconf.h,v 1.40 2001/10/01 21:51:16 markus Exp $"); */ - #ifndef READCONF_H #define READCONF_H @@ -81,7 +81,7 @@ typedef struct { 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; diff --git a/openssh/readpass.c b/openssh/readpass.c index a042981..b4421ad 100644 --- a/openssh/readpass.c +++ b/openssh/readpass.c @@ -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,29 +9,21 @@ * 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.23 2001/11/08 10:51:08 markus Exp $"); +RCSID("$OpenBSD: readpass.c,v 1.26 2002/02/13 00:39:15 markus Exp $"); #include "xmalloc.h" #include "readpass.h" @@ -46,7 +37,7 @@ ssh_askpass(char *askpass, const char *msg) pid_t pid; size_t len; char *pass; - int p[2], status; + int p[2], status, ret; char buf[1024]; if (fflush(stdout) != 0) @@ -71,14 +62,23 @@ ssh_askpass(char *askpass, const char *msg) fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno)); } close(p[1]); - len = read(p[0], buf, sizeof buf -1); + + 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(""); - buf[len] = '\0'; + buf[strcspn(buf, "\r\n")] = '\0'; pass = xstrdup(buf); memset(buf, 0, sizeof(buf)); @@ -103,7 +103,7 @@ read_passphrase(const char *prompt, int flags) use_askpass = 1; } else { rppflags |= RPP_REQUIRE_TTY; - ttyfd = open("/dev/tty", O_RDWR); + ttyfd = open(_PATH_TTY, O_RDWR); if (ttyfd >= 0) close(ttyfd); else diff --git a/openssh/rijndael.c b/openssh/rijndael.c index f28a9c6..c8ba55e 100644 --- a/openssh/rijndael.c +++ b/openssh/rijndael.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rijndael.c,v 1.12 2001/09/13 09:48:39 markus Exp $ */ +/* $OpenBSD: rijndael.c,v 1.13 2001/12/19 07:18:56 deraadt Exp $ */ /** * rijndael-alg-fst.c @@ -775,32 +775,31 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int 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]; - + 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; - } + } } return 0; } @@ -917,28 +916,28 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16 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]; - } + /* 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 */ @@ -947,60 +946,60 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16 */ 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]; + 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; - } + rk += 8; + if (--r == 0) { + break; + } - 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]; + 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 */ /* @@ -1098,28 +1097,28 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16 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]; - } + /* 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]; + } } rk += Nr << 2; #else /* !FULL_UNROLL */ @@ -1128,60 +1127,60 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16 */ 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]; + 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; - } + rk += 8; + if (--r == 0) { + break; + } - 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]; + 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 */ /* @@ -1222,13 +1221,13 @@ void rijndael_set_key(rijndael_ctx *ctx, u_char *key, int bits, int encrypt) { ctx->Nr = rijndaelKeySetupEnc(ctx->ek, key, bits); - if (encrypt) { + 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); + rijndaelKeySetupDec(ctx->dk, key, bits, ctx->Nr); } } diff --git a/openssh/rijndael.h b/openssh/rijndael.h index 18a4d80..c614bb1 100644 --- a/openssh/rijndael.h +++ b/openssh/rijndael.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rijndael.h,v 1.11 2001/09/13 09:48:39 markus Exp $ */ +/* $OpenBSD: rijndael.h,v 1.12 2001/12/19 07:18:56 deraadt Exp $ */ /** * rijndael-alg-fst.h @@ -32,8 +32,8 @@ #define MAXKB (256/8) #define MAXNR 14 -typedef unsigned char u8; -typedef unsigned short u16; +typedef unsigned char u8; +typedef unsigned short u16; typedef unsigned int u32; /* The structure for key information */ diff --git a/openssh/rsa.c b/openssh/rsa.c index 113ee7f..66561a4 100644 --- a/openssh/rsa.c +++ b/openssh/rsa.c @@ -60,7 +60,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: rsa.c,v 1.23 2001/06/27 05:42:24 markus Exp $"); +RCSID("$OpenBSD: rsa.c,v 1.24 2001/12/27 18:22:16 markus Exp $"); #include "rsa.h" #include "log.h" @@ -120,14 +120,17 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) return len; } +/* calculate p-1 and q-1 */ void 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); diff --git a/openssh/rsa.h b/openssh/rsa.h index 2f596d4..957d865 100644 --- a/openssh/rsa.h +++ b/openssh/rsa.h @@ -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,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: rsa.h,v 1.14 2001/06/27 05:42:24 markus Exp $"); */ - #ifndef RSA_H #define RSA_H diff --git a/openssh/scard.c b/openssh/scard.c index 251e5d3..e831931 100644 --- a/openssh/scard.c +++ b/openssh/scard.c @@ -24,7 +24,7 @@ #include "includes.h" #ifdef SMARTCARD -RCSID("$OpenBSD: scard.c,v 1.15 2001/09/28 09:49:31 djm Exp $"); +RCSID("$OpenBSD: scard.c,v 1.17 2001/12/27 18:22:16 markus Exp $"); #include #include @@ -48,7 +48,7 @@ static int cla = 0x00; /* class */ /* interface to libsectok */ -static int +static int sc_open(void) { int sw; @@ -79,7 +79,7 @@ sc_open(void) return sc_fd; } -static int +static int sc_enable_applet(void) { static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e}; @@ -95,7 +95,7 @@ sc_enable_applet(void) return 0; } -static int +static int sc_init(void) { int status; @@ -115,7 +115,7 @@ sc_init(void) return 0; } -static int +static int sc_read_pubkey(Key * k) { u_char buf[2], *n; @@ -133,7 +133,7 @@ sc_read_pubkey(Key * k) /* get key size */ sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL, - sizeof(buf), buf, &sw); + sizeof(buf), buf, &sw); if (!sectok_swOK(sw)) { error("could not obtain key length: %s", sectok_get_sw(sw)); goto err; @@ -204,7 +204,7 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding) goto err; } sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL, - len, padded, &sw); + len, padded, &sw); if (!sectok_swOK(sw)) { error("sc_private_decrypt: INS_GET_RESPONSE failed: %s", sectok_get_sw(sw)); @@ -249,7 +249,7 @@ sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding) goto err; } sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL, - len, to, &sw); + len, to, &sw); if (!sectok_swOK(sw)) { error("sc_private_decrypt: INS_GET_RESPONSE failed: %s", sectok_get_sw(sw)); @@ -320,7 +320,8 @@ sc_get_engine(void) smart_rsa.rsa_sign = def->rsa_sign; smart_rsa.rsa_verify = def->rsa_verify; - smart_engine = ENGINE_new(); + if ((smart_engine = ENGINE_new()) == NULL) + fatal("ENGINE_new failed"); ENGINE_set_id(smart_engine, "sectok"); ENGINE_set_name(smart_engine, "libsectok"); diff --git a/openssh/scard.h b/openssh/scard.h index 57189df..6ca9916 100644 --- a/openssh/scard.h +++ b/openssh/scard.h @@ -1,3 +1,5 @@ +/* $OpenBSD: scard.h,v 1.7 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -22,8 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $OpenBSD: scard.h,v 1.6 2001/08/01 22:03:33 markus Exp $ */ - #include #ifndef SCARD_H diff --git a/openssh/scard/.cvsignore b/openssh/scard/.cvsignore new file mode 100644 index 0000000..5349d34 --- /dev/null +++ b/openssh/scard/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Ssh.bin diff --git a/openssh/scp.1 b/openssh/scp.1 index d51e680..69125c1 100644 --- a/openssh/scp.1 +++ b/openssh/scp.1 @@ -9,7 +9,7 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.20 2001/09/17 23:56:07 stevesk Exp $ +.\" $OpenBSD: scp.1,v 1.21 2002/01/29 23:50:37 markus Exp $ .\" .Dd September 25, 1999 .Dt SCP 1 @@ -134,6 +134,9 @@ Forces .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 diff --git a/openssh/scp.c b/openssh/scp.c index fb4d309..83e7769 100644 --- a/openssh/scp.c +++ b/openssh/scp.c @@ -75,7 +75,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.85 2001/10/01 08:06:28 markus Exp $"); +RCSID("$OpenBSD: scp.c,v 1.86 2001/12/05 03:56:39 itojun Exp $"); #include "xmalloc.h" #include "atomicio.h" @@ -548,14 +548,13 @@ syserr: run_err("%s: %s", name, strerror(errno)); #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); + (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); @@ -930,7 +929,7 @@ screwup: } int -response() +response(void) { char ch, *cp, resp, rbuf[2048]; @@ -963,7 +962,7 @@ response() } void -usage() +usage(void) { (void) fprintf(stderr, "usage: scp [-pqrvBC46] [-F config] [-S ssh] [-P port] [-c cipher] [-i identity]\n" diff --git a/openssh/servconf.c b/openssh/servconf.c index e914d4c..9bbd994 100644 --- a/openssh/servconf.c +++ b/openssh/servconf.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.91 2001/11/12 18:17:07 markus Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $"); #if defined(KRB4) || defined(KRB5) #include @@ -63,11 +63,12 @@ initialize_server_options(ServerOptions *options) options->print_lastlog = -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; @@ -104,7 +105,7 @@ initialize_server_options(ServerOptions *options) 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; @@ -124,9 +125,14 @@ fill_default_server_options(ServerOptions *options) 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_RSA_KEY_FILE; + 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; @@ -154,17 +160,17 @@ fill_default_server_options(ServerOptions *options) options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; -#ifdef _PATH_XAUTH + if (options->x11_use_localhost == -1) + options->x11_use_localhost = 1; if (options->xauth_location == NULL) options->xauth_location = _PATH_XAUTH; -#endif 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; @@ -190,7 +196,7 @@ fill_default_server_options(ServerOptions *options) if (options->kerberos_tgt_passing == -1) options->kerberos_tgt_passing = 0; #endif -#ifdef AFS +#ifdef AFS if (options->afs_token_passing == -1) options->afs_token_passing = k_hasafs(); #endif @@ -214,10 +220,10 @@ fill_default_server_options(ServerOptions *options) 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) { @@ -252,16 +258,16 @@ typedef enum { sChallengeResponseAuthentication, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, sStrictModes, sEmptyPasswd, sKeepAlives, sUseLogin, sAllowTcpForwarding, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, - sBanner, sReverseMappingCheck, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sBanner, sVerifyReverseMapping, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sDeprecated + sDeprecated } ServerOpCodes; /* Textual representation of the tokens. */ @@ -312,6 +318,7 @@ static struct { { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, { "x11forwarding", sX11Forwarding }, { "x11displayoffset", sX11DisplayOffset }, + { "x11uselocalhost", sX11UseLocalhost }, { "xauthlocation", sXAuthLocation }, { "strictmodes", sStrictModes }, { "permitemptypasswords", sEmptyPasswd }, @@ -329,12 +336,13 @@ static struct { { "subsystem", sSubsystem }, { "maxstartups", sMaxStartups }, { "banner", sBanner }, - { "reversemappingcheck", sReverseMappingCheck }, + { "verifyreversemapping", sVerifyReverseMapping }, + { "reversemappingcheck", sVerifyReverseMapping }, { "clientaliveinterval", sClientAliveInterval }, { "clientalivecountmax", sClientAliveCountMax }, { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, - { NULL, 0 } + { NULL, sBadOption } }; /* @@ -392,487 +400,501 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port) 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; ServerOpCodes opcode; int i, n; - 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; - - /* Portable-specific options */ - case sPAMAuthenticationViaKbdInt: - intptr = &options->pam_authentication_via_kbd_int; - goto parse_flag; - - /* Standard Options */ - 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.", 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; - case sServerKeyBits: - intptr = &options->server_key_bits; + /* 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; parse_int: - 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; + 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.", + 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); - 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 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.", + 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 sIgnoreUserKnownHosts: - intptr = &options->ignore_user_known_hosts; - goto parse_flag; + case sKerberosOrLocalPasswd: + intptr = &options->kerberos_or_local_passwd; + goto parse_flag; - case sRhostsAuthentication: - intptr = &options->rhosts_authentication; - 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 sRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; - case sHostbasedAuthentication: - intptr = &options->hostbased_authentication; - goto parse_flag; + case sKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; - case sHostbasedUsesNameFromPacketOnly: - intptr = &options->hostbased_uses_name_from_packet_only; - goto parse_flag; + case sChallengeResponseAuthentication: + intptr = &options->challenge_response_authentication; + goto parse_flag; - case sRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; + case sPrintMotd: + intptr = &options->print_motd; + 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 sPrintLastLog: + intptr = &options->print_lastlog; + goto parse_flag; - case sKerberosOrLocalPasswd: - intptr = &options->kerberos_or_local_passwd; - goto parse_flag; + case sX11Forwarding: + intptr = &options->x11_forwarding; + 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 sX11DisplayOffset: + intptr = &options->x11_display_offset; + goto parse_int; - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; - - case sKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; - - case sChallengeResponseAuthentication: - intptr = &options->challenge_response_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 sX11UseLocalhost: + intptr = &options->x11_use_localhost; + 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 sXAuthLocation: + charptr = &options->xauth_location; + goto parse_filename; - case sAllowTcpForwarding: - intptr = &options->allow_tcp_forwarding; - goto parse_flag; + case sStrictModes: + intptr = &options->strict_modes; + 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 sKeepAlives: + intptr = &options->keepalives; + goto parse_flag; - 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 sEmptyPasswd: + intptr = &options->permit_empty_passwd; + goto parse_flag; - 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 sUseLogin: + intptr = &options->use_login; + goto parse_flag; - 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 sGatewayPorts: + intptr = &options->gateway_ports; + 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 sVerifyReverseMapping: + intptr = &options->verify_reverse_mapping; + goto parse_flag; - 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 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 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 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 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 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 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 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) + 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 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); + } + 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 - options->max_startups = options->max_startups_begin; - break; + } 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 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; +} - 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 sDeprecated: - log("%s line %d: Deprecated option %s", - filename, linenum, arg); - while(arg) - arg = strdelim(&cp); - break; +/* Reads the server configuration file. */ - 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); +void +read_server_config(ServerOptions *options, const char *filename) +{ + FILE *f; + char line[1024]; + int linenum; + int bad_options = 0; + + 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) diff --git a/openssh/servconf.h b/openssh/servconf.h index 2e10b1c..3134b22 100644 --- a/openssh/servconf.h +++ b/openssh/servconf.h @@ -1,3 +1,5 @@ +/* $OpenBSD: servconf.h,v 1.54 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". */ -/* RCSID("$OpenBSD: servconf.h,v 1.49 2001/08/17 18:59:47 stevesk Exp $"); */ - #ifndef SERVCONF_H #define SERVCONF_H @@ -55,6 +55,7 @@ typedef struct { 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. */ @@ -115,15 +116,15 @@ typedef struct { 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, - * disconnect the session + * disconnect the session */ char *authorized_keys_file; /* File containing public keys */ @@ -135,5 +136,7 @@ typedef struct { 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); + #endif /* SERVCONF_H */ diff --git a/openssh/serverloop.c b/openssh/serverloop.c index 0da805f..46b12ee 100644 --- a/openssh/serverloop.c +++ b/openssh/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.83 2001/11/09 18:59:23 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.98 2002/02/06 14:55:16 markus Exp $"); #include "xmalloc.h" #include "packet.h" @@ -87,11 +87,56 @@ static int client_alive_timeouts = 0; * will exit after that, as soon as forwarded connections have terminated. */ -static volatile int child_terminated; /* The child has terminated. */ +static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ /* prototypes */ static void server_init_dispatch(void); +/* + * 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) +{ + 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; + + if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) + while (read(notify_pipe[0], &c, 1) != -1) + debug2("notify_done: reading"); +} + static void sigchld_handler(int sig) { @@ -99,6 +144,7 @@ sigchld_handler(int sig) debug("Received SIGCHLD."); child_terminated = 1; mysignal(SIGCHLD, sigchld_handler); + notify_parent(); errno = save_errno; } @@ -163,15 +209,21 @@ make_packets_from_stdout_data(void) 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."); - id = channel_find_open(); - if (id == -1) - packet_disconnect("No open channels after timeout!"); /* * send a bogus channel request with "wantreply", * we should get back a failure @@ -195,12 +247,12 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, 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 (compat20 && max_time_milliseconds == 0 && options.client_alive_interval) { @@ -242,6 +294,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, 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 @@ -266,7 +319,8 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, tvp = &tv; } if (tvp!=NULL) - debug3("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds); + debug3("tvp!=NULL kid %d mili %d", (int) child_terminated, + max_time_milliseconds); /* Wait for something to happen, or the timeout to expire. */ ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); @@ -278,6 +332,8 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, error("select: %.100s", strerror(errno)); } else if (ret == 0 && client_alive_scheduled) client_alive_check(); + + notify_done(*readsetp); } /* @@ -356,14 +412,10 @@ process_output(fd_set * writeset) 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. */ @@ -467,6 +519,8 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) 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. */ @@ -511,14 +565,10 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) * 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. */ @@ -572,6 +622,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) 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, @@ -597,7 +648,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) 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); @@ -622,7 +673,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) /* We no longer want our SIGCHLD handler to be called. */ mysignal(SIGCHLD, SIG_DFL); - wait_pid = waitpid(-1, &wait_status, child_terminated ? WNOHANG : 0); + wait_pid = waitpid(-1, &wait_status, 0); if (wait_pid == -1) packet_disconnect("wait: %.100s", strerror(errno)); else if (wait_pid != pid) @@ -646,8 +697,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) * the exit status. */ do { - int plen; - type = packet_read(&plen); + type = packet_read(); } while (type != SSH_CMSG_EXIT_CONFIRMATION); @@ -696,7 +746,11 @@ server_loop2(Authctxt *authctxt) 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(); @@ -734,20 +788,20 @@ server_loop2(Authctxt *authctxt) } static void -server_input_channel_failure(int type, int plen, void *ctxt) +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. * 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; } static void -server_input_stdin_data(int type, int plen, void *ctxt) +server_input_stdin_data(int type, u_int32_t seq, void *ctxt) { char *data; u_int data_len; @@ -757,14 +811,14 @@ server_input_stdin_data(int type, int plen, void *ctxt) 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); } static void -server_input_eof(int type, int plen, void *ctxt) +server_input_eof(int type, u_int32_t seq, void *ctxt) { /* * Eof from the client. The stdin descriptor to the @@ -772,12 +826,12 @@ server_input_eof(int type, int plen, void *ctxt) * drained. */ debug("EOF received for stdin."); - packet_integrity_check(plen, 0, type); + packet_check_eom(); stdin_eof = 1; } static void -server_input_window_size(int type, int plen, void *ctxt) +server_input_window_size(int type, u_int32_t seq, void *ctxt) { int row = packet_get_int(); int col = packet_get_int(); @@ -785,7 +839,7 @@ server_input_window_size(int type, int plen, void *ctxt) 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); } @@ -802,7 +856,7 @@ server_request_direct_tcpip(char *ctype) 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); @@ -816,10 +870,6 @@ server_request_direct_tcpip(char *ctype) c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); - if (c == NULL) { - error("server_request_direct_tcpip: channel_new failed"); - close(sock); - } return c; } @@ -829,7 +879,7 @@ server_request_session(char *ctype) 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 @@ -839,23 +889,17 @@ server_request_session(char *ctype) c = channel_new(ctype, SSH_CHANNEL_LARVAL, -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, xstrdup("server-session"), 1); - if (c == NULL) { - error("server_request_session: channel_new failed"); - return NULL; - } if (session_open(xxx_authctxt, c->self) != 1) { debug("session open failed, free channel %d", c->self); channel_free(c); return NULL; } - channel_register_callback(c->self, SSH2_MSG_CHANNEL_REQUEST, - session_input_channel_req, (void *)0); channel_register_cleanup(c->self, session_close_by_channel); return c; } static void -server_input_channel_open(int type, int plen, void *ctxt) +server_input_channel_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; char *ctype; @@ -905,7 +949,7 @@ server_input_channel_open(int type, int plen, void *ctxt) } static void -server_input_global_request(int type, int plen, void *ctxt) +server_input_global_request(int type, u_int32_t seq, void *ctxt) { char *rtype; int want_reply; @@ -937,11 +981,8 @@ server_input_global_request(int type, int plen, void *ctxt) 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); } @@ -953,6 +994,33 @@ server_input_global_request(int type, int plen, void *ctxt) } 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; + + 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) @@ -966,7 +1034,7 @@ server_init_dispatch_20(void) 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 */ diff --git a/openssh/session.c b/openssh/session.c index 02c0c52..a31ff85 100644 --- a/openssh/session.c +++ b/openssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.108 2001/10/11 13:45:21 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -57,41 +57,12 @@ RCSID("$OpenBSD: session.c,v 1.108 2001/10/11 13:45:21 markus Exp $"); #include "canohost.h" #include "session.h" -#ifdef WITH_IRIX_PROJECT -#include -#endif /* WITH_IRIX_PROJECT */ -#ifdef WITH_IRIX_JOBS -#include -#endif -#ifdef WITH_IRIX_AUDIT -#include -#endif /* WITH_IRIX_AUDIT */ - -#if defined(HAVE_USERSEC_H) -#include -#endif - #ifdef HAVE_CYGWIN #include #include #define is_winnt (GetVersion() < 0x80000000) #endif -/* AIX limits */ -#if defined(HAVE_GETUSERATTR) && !defined(S_UFSIZE_HARD) && defined(S_UFSIZE) -# define S_UFSIZE_HARD S_UFSIZE "_hard" -# define S_UCPU_HARD S_UCPU "_hard" -# define S_UDATA_HARD S_UDATA "_hard" -# define S_USTACK_HARD S_USTACK "_hard" -# define S_URSS_HARD S_URSS "_hard" -# define S_UCORE_HARD S_UCORE "_hard" -# define S_UNOFILE_HARD S_UNOFILE "_hard" -#endif - -#ifdef _AIX -# include -#endif - /* types */ #define TTYSZ 64 @@ -108,8 +79,10 @@ struct Session { int row, col, xpixel, ypixel; char tty[TTYSZ]; /* X11 */ + int display_number; char *display; int screen; + char *auth_display; char *auth_proto; char *auth_data; int single_connection; @@ -193,7 +166,7 @@ do_authenticated(Authctxt *authctxt) #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.reverse_mapping_check), + get_canonical_hostname(options.verify_reverse_mapping), "ssh", &aixloginmsg) < 0) aixloginmsg = NULL; #endif /* WITH_AIXAUTHENTICATE */ @@ -231,7 +204,7 @@ do_authenticated1(Authctxt *authctxt) { Session *s; char *command; - int success, type, plen, screen_flag; + int success, type, screen_flag; int compression_level = 0, enable_compression_after_reply = 0; u_int proto_len, data_len, dlen; @@ -247,16 +220,16 @@ do_authenticated1(Authctxt *authctxt) 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; } /* Enable compression after we have responded with SUCCESS. */ @@ -284,7 +257,7 @@ do_authenticated1(Authctxt *authctxt) } else { s->screen = 0; } - packet_done(); + packet_check_eom(); success = session_setup_x11fwd(s); if (!success) { xfree(s->auth_proto); @@ -321,22 +294,22 @@ do_authenticated1(Authctxt *authctxt) if (packet_set_maxsize(packet_get_int()) > 0) 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_integrity_check(plen, 4 + dlen, type); - + 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 @@ -354,7 +327,7 @@ do_authenticated1(Authctxt *authctxt) } break; #endif /* AFS || KRB5 */ - + #ifdef AFS case SSH_CMSG_HAVE_AFS_TOKEN: if (!options.afs_token_passing || !k_hasafs()) { @@ -362,8 +335,8 @@ do_authenticated1(Authctxt *authctxt) } else { /* Accept AFS token. */ char *token = packet_get_string(&dlen); - packet_integrity_check(plen, 4 + dlen, type); - + packet_check_eom(); + if (auth_afs_token(s->authctxt, token)) success = 1; else @@ -384,7 +357,7 @@ do_authenticated1(Authctxt *authctxt) } else { do_exec(s, NULL); } - packet_done(); + packet_check_eom(); session_close(s); return; @@ -647,14 +620,14 @@ do_pre_login(Session *s) 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(); } } record_utmp_only(pid, s->tty, s->pw->pw_name, - get_remote_name_or_ip(utmp_len, options.reverse_mapping_check), + get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), (struct sockaddr *)&from); } #endif @@ -680,6 +653,7 @@ do_exec(Session *s, const char *command) original_command = NULL; } + /* administrative, login(1)-like work */ void do_login(Session *s, const char *command) @@ -700,7 +674,7 @@ do_login(Session *s, const char *command) 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(); } @@ -715,7 +689,7 @@ do_login(Session *s, const char *command) /* 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), + get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), (struct sockaddr *)&from); #ifdef USE_PAM @@ -809,7 +783,7 @@ check_quietlogin(Session *s, const char *command) */ 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; @@ -850,7 +824,7 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, */ static void read_environment_file(char ***env, u_int *envsize, - const char *filename) + const char *filename) { FILE *f; char buf[4096]; @@ -883,325 +857,36 @@ read_environment_file(char ***env, u_int *envsize, fclose(f); } -#ifdef USE_PAM -/* - * Sets any environment variables which have been specified by PAM - */ -void do_pam_environment(char ***env, u_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) + for(i = 0; source[i] != NULL; i++) { + var_name = xstrdup(source[i]); + if ((var_val = strstr(var_name, "=")) == NULL) { + xfree(var_name); 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); - - debug3("PAM environment: %s=%s", var_name, var_val); - - child_set_env(env, envsize, var_name, var_val); } - } -} -#endif /* USE_PAM */ - -#ifdef HAVE_CYGWIN -void copy_environment(char ***env, u_int *envsize) -{ - char *equals, var_name[512], var_val[512]; - int i; - - for(i = 0; environ[i] != NULL; i++) { - if ((equals = strstr(environ[i], "=")) == NULL) - continue; - - if (strlen(environ[i]) < (sizeof(var_name) - 1)) { - memset(var_name, '\0', sizeof(var_name)); - memset(var_val, '\0', sizeof(var_val)); + *var_val++ = '\0'; - strncpy(var_name, environ[i], equals - environ[i]); - strcpy(var_val, equals + 1); - - debug3("Copy environment: %s=%s", var_name, var_val); - - child_set_env(env, envsize, var_name, var_val); - } - } -} -#endif - -#if defined(HAVE_GETUSERATTR) -/* - * AIX-specific login initialisation - */ -void set_limit(char *user, char *soft, char *hard, int resource, int mult) -{ - struct rlimit rlim; - int slim, hlim; - - getrlimit(resource, &rlim); - - slim = 0; - if (getuserattr(user, soft, &slim, SEC_INT) != -1) { - if (slim < 0) { - rlim.rlim_cur = RLIM_INFINITY; - } else if (slim != 0) { - /* See the wackiness below */ - if (rlim.rlim_cur == slim * mult) - slim = 0; - else - rlim.rlim_cur = slim * mult; - } - } - - hlim = 0; - if (getuserattr(user, hard, &hlim, SEC_INT) != -1) { - if (hlim < 0) { - rlim.rlim_max = RLIM_INFINITY; - } else if (hlim != 0) { - rlim.rlim_max = hlim * mult; - } - } - - /* - * XXX For cpu and fsize the soft limit is set to the hard limit - * if the hard limit is left at its default value and the soft limit - * is changed from its default value, either by requesting it - * (slim == 0) or by setting it to the current default. At least - * that's how rlogind does it. If you're confused you're not alone. - * Bug or feature? AIX 4.3.1.2 - */ - if ((!strcmp(soft, "fsize") || !strcmp(soft, "cpu")) - && hlim == 0 && slim != 0) - rlim.rlim_max = rlim.rlim_cur; - /* A specified hard limit limits the soft limit */ - else if (hlim > 0 && rlim.rlim_cur > rlim.rlim_max) - rlim.rlim_cur = rlim.rlim_max; - /* A soft limit can increase a hard limit */ - else if (rlim.rlim_cur > rlim.rlim_max) - rlim.rlim_max = rlim.rlim_cur; - - if (setrlimit(resource, &rlim) != 0) - error("setrlimit(%.10s) failed: %.100s", soft, strerror(errno)); -} - -void set_limits_from_userattr(char *user) -{ - int mask; - char buf[16]; - - set_limit(user, S_UFSIZE, S_UFSIZE_HARD, RLIMIT_FSIZE, 512); - set_limit(user, S_UCPU, S_UCPU_HARD, RLIMIT_CPU, 1); - set_limit(user, S_UDATA, S_UDATA_HARD, RLIMIT_DATA, 512); - set_limit(user, S_USTACK, S_USTACK_HARD, RLIMIT_STACK, 512); - set_limit(user, S_URSS, S_URSS_HARD, RLIMIT_RSS, 512); - set_limit(user, S_UCORE, S_UCORE_HARD, RLIMIT_CORE, 512); -#if defined(S_UNOFILE) - set_limit(user, S_UNOFILE, S_UNOFILE_HARD, RLIMIT_NOFILE, 1); -#endif - - if (getuserattr(user, S_UMASK, &mask, SEC_INT) != -1) { - /* Convert decimal to octal */ - (void) snprintf(buf, sizeof(buf), "%d", mask); - if (sscanf(buf, "%o", &mask) == 1) - umask(mask); + debug3("Copy environment: %s=%s", var_name, var_val); + child_set_env(env, envsize, var_name, var_val); + + xfree(var_name); } } -#endif /* defined(HAVE_GETUSERATTR) */ -/* - * 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; + u_int i, envsize; char **env; - extern char **environ; - struct stat st; - char *argv[10]; - int do_xauth; -#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 */ - - do_xauth = - s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; - - /* 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; - -#if !defined(HAVE_OSF_SIA) - 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 /* HAVE_LOGIN_CAP */ - if (pw->pw_uid) - f = fopen(_PATH_NOLOGIN, "r"); -# endif /* HAVE_LOGIN_CAP */ - if (f) { - /* /etc/nologin exists. Print its contents and exit. */ - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stderr); - fclose(f); - exit(254); - } - } -#endif /* HAVE_OSF_SIA */ - - /* 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_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 */ -#ifdef HAVE_CYGWIN - if (is_winnt) { -#else - if (getuid() == 0 || geteuid() == 0) { -#endif -# ifdef HAVE_GETUSERATTR - set_limits_from_userattr(pw->pw_name); -# endif /* HAVE_GETUSERATTR */ -# 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 /* HAVE_LOGIN_CAP */ -#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 */ -# 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) { - if (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 */ - -#ifdef _AIX - /* - * 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 - */ - if (s->ttyfd == -1) - s->tty[0] = '\0'; - cp = xmalloc(22 + strlen(s->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, s->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 - - /* Permanently switch to the desired uid. */ - permanently_set_uid(pw); -# endif /* HAVE_LOGIN_CAP */ - } -#endif /* HAVE_OSF_SIA */ - -#ifdef HAVE_CYGWIN - if (is_winnt) -#endif - 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 + struct passwd *pw = s->pw; /* Initialize the environment. */ envsize = 100; @@ -1213,7 +898,7 @@ do_child(Session *s, const char *command) * The Windows environment contains some setting which are * important for a running system. They must not be dropped. */ - copy_environment(&env, &envsize); + copy_environment(environ, &env, &envsize); #endif if (!options.use_login) { @@ -1251,7 +936,7 @@ do_child(Session *s, const char *command) 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] == '=') { @@ -1265,7 +950,7 @@ do_child(Session *s, const char *command) } 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) @@ -1279,11 +964,15 @@ do_child(Session *s, const char *command) original_command); #ifdef _AIX - 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"); + { + char *cp; + + 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 #ifdef KRB4 if (s->authctxt->krb4_ticket_file) @@ -1297,12 +986,12 @@ do_child(Session *s, const char *command) #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 (auth_get_socket_name() != NULL) child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, - auth_get_socket_name()); + auth_get_socket_name()); /* read $HOME/.ssh/environment. */ if (!options.use_login) { @@ -1316,10 +1005,210 @@ do_child(Session *s, const char *command) 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 %.100s 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. */ +static void +do_setusercontext(struct passwd *pw) +{ +#ifdef HAVE_CYGWIN + if (is_winnt) { +#else /* HAVE_CYGWIN */ + if (getuid() == 0 || geteuid() == 0) { +#endif /* HAVE_CYGWIN */ +#ifdef HAVE_GETUSERATTR + set_limits_from_userattr(pw->pw_name); +#endif /* HAVE_GETUSERATTR */ +#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 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) */ + /* 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); +} + +/* + * 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); +# ifdef _AIX + aix_usrinfo(pw, s->tty, s->ttyfd); +# endif /* _AIX */ + 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 @@ -1356,8 +1245,8 @@ do_child(Session *s, const char *command) 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; @@ -1365,10 +1254,10 @@ do_child(Session *s, const char *command) /* 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 */ @@ -1383,128 +1272,65 @@ do_child(Session *s, const char *command) #endif } - /* - * 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; - } + if (!options.use_login) + do_rc_files(s, shell); /* restore SIGPIPE for child */ signal(SIGPIPE, SIG_DFL); + if (options.use_login) { + /* Launch login(1). */ + + execl(LOGIN_PROGRAM, "login", "-h", hostname, +#ifdef LOGIN_NEEDS_TERM + (s->term ? s->term : "unknown"), +#endif /* LOGIN_NEEDS_TERM */ + "-p", "-f", "--", pw->pw_name, (char *)NULL); + + /* Login couldn't be executed, die. */ + + perror("login"); + exit(1); + } + + /* 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]; - /* Start the shell. Set initial character to '-'. */ - buf[0] = '-'; - strncpy(buf + 1, cp, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; + /* Start the shell. Set initial character to '-'. */ + argv0[0] = '-'; - /* Execute the shell. */ - argv[0] = buf; - argv[1] = NULL; - execve(shell, argv, env); - - /* 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(LOGIN_PROGRAM, "login", "-h", hostname, -#ifdef LOGIN_NEEDS_TERM - s->term? s->term : "unknown", -#endif - "-p", "-f", "--", pw->pw_name, (char *)NULL); - - /* Login couldn't be executed, die. */ + /* Execute the shell. */ + argv[0] = argv0; + argv[1] = NULL; + execve(shell, argv, env); - perror("login"); - exit(1); - } + /* 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; @@ -1520,12 +1346,12 @@ session_new(void) 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; } 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)); @@ -1545,7 +1371,7 @@ 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", s->used, @@ -1578,7 +1404,7 @@ 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); @@ -1595,7 +1421,7 @@ session_by_pid(pid_t pid) { int i; debug("session_by_pid: pid %d", pid); - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; @@ -1612,7 +1438,7 @@ session_window_change_req(Session *s) 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; } @@ -1677,7 +1503,7 @@ session_pty_req(Session *s) /* Set window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); - packet_done(); + packet_check_eom(); session_proctitle(s); return 1; } @@ -1691,8 +1517,8 @@ session_subsystem_req(Session *s) 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) { @@ -1706,11 +1532,12 @@ session_subsystem_req(Session *s) s->is_subsystem = 1; do_exec(s, cmd); success = 1; + break; } } if (!success) - log("subsystem request for %s failed, subsystem not found", + log("subsystem request for %.100s failed, subsystem not found", subsys); xfree(subsys); @@ -1726,7 +1553,7 @@ session_x11_req(Session *s) s->auth_proto = packet_get_string(NULL); s->auth_data = packet_get_string(NULL); s->screen = packet_get_int(); - packet_done(); + packet_check_eom(); success = session_setup_x11fwd(s); if (!success) { @@ -1741,7 +1568,7 @@ session_x11_req(Session *s) static int session_shell_req(Session *s) { - packet_done(); + packet_check_eom(); do_exec(s, NULL); return 1; } @@ -1751,7 +1578,7 @@ session_exec_req(Session *s) { u_int len; char *command = packet_get_string(&len); - packet_done(); + packet_check_eom(); do_exec(s, command); xfree(command); return 1; @@ -1761,7 +1588,7 @@ 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; @@ -1774,28 +1601,18 @@ session_auth_agent_req(Session *s) } } -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 @@ -1819,14 +1636,7 @@ session_input_channel_req(int id, void *arg) 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 @@ -1843,7 +1653,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr) channel_set_fds(s->chanid, fdout, fdin, fderr, fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1); + 1, + CHAN_SES_WINDOW_DEFAULT); } /* @@ -1866,7 +1677,7 @@ session_pty_cleanup(void *session) /* Record that the user has logged out. */ if (s->pid != 0) - record_logout(s->pid, s->tty); + record_logout(s->pid, s->tty, s->pw->pw_name); /* Release the pseudo-tty. */ pty_release(s->tty); @@ -1887,23 +1698,19 @@ 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) + + 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); 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)); @@ -1944,6 +1751,8 @@ session_close(Session *s) 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) @@ -2000,9 +1809,9 @@ void session_destroy_all(void) { int i; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; - if (s->used) + if (s->used) session_close(s); } } @@ -2013,7 +1822,7 @@ 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') @@ -2039,6 +1848,8 @@ 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."); @@ -2062,11 +1873,50 @@ session_setup_x11fwd(Session *s) debug("X11 display already set."); return 0; } - s->display = x11_create_display_inet(s->screen, options.x11_display_offset); - if (s->display == NULL) { + s->display_number = x11_create_display_inet(options.x11_display_offset, + options.x11_use_localhost, s->single_connection); + if (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:%d.%d", + s->display_number, s->screen); + snprintf(auth_display, sizeof auth_display, "unix:%d.%d", + 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:%d.%d", inet_ntoa(my_addr), + s->display_number, s->screen); +#else + snprintf(display, sizeof display, "%.400s:%d.%d", hostname, + s->display_number, s->screen); +#endif + s->display = xstrdup(display); + s->auth_display = xstrdup(display); + } + return 1; } diff --git a/openssh/session.h b/openssh/session.h index 6d5b8e6..ec8284a 100644 --- a/openssh/session.h +++ b/openssh/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.13 2001/10/10 22:18:47 markus Exp $ */ +/* $OpenBSD: session.h,v 1.14 2002/02/03 17:53:25 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -29,7 +29,7 @@ void do_authenticated(Authctxt *); int session_open(Authctxt*, int); -void session_input_channel_req(int, void *); +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); diff --git a/openssh/sftp-client.c b/openssh/sftp-client.c index 4f2a1e2..17ac14a 100644 --- a/openssh/sftp-client.c +++ b/openssh/sftp-client.c @@ -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,12 +24,17 @@ /* 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.18 2001/07/14 15:10:16 stevesk Exp $"); +RCSID("$OpenBSD: sftp-client.c,v 1.24 2002/02/24 16:57:19 markus Exp $"); + +#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) +#include +#else +#include "openbsd-compat/fake-queue.h" +#endif #include "buffer.h" #include "bufaux.h" @@ -42,12 +47,17 @@ RCSID("$OpenBSD: sftp-client.c,v 1.18 2001/07/14 15:10:16 stevesk Exp $"); #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; +}; static void send_msg(int fd, Buffer *m) @@ -215,11 +225,12 @@ get_decode_stat(int fd, u_int expected_id, int quiet) 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; Buffer msg; + struct sftp_conn *ret; buffer_init(&msg); buffer_put_char(&msg, SSH2_FXP_INIT); @@ -235,7 +246,7 @@ do_init(int fd_in, int fd_out) error("Invalid packet back from SSH2_FXP_INIT (type %d)", type); buffer_free(&msg); - return(-1); + return(NULL); } version = buffer_get_int(&msg); @@ -253,25 +264,43 @@ do_init(int fd_in, int fd_out) 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 = MAX(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); + send_msg(conn->fd_out, &msg); debug3("Sent message SSH2_FXP_CLOSE I:%d", 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)); @@ -282,24 +311,24 @@ do_close(int fd_in, int fd_out, char *handle, u_int handle_len) static int -do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, +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); @@ -308,12 +337,11 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, *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); @@ -321,11 +349,11 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, 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); @@ -345,7 +373,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, } 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) @@ -356,7 +384,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, 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; @@ -383,29 +411,29 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, } 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]); @@ -414,30 +442,31 @@ void free_sftp_dirents(SFTP_DIRENT **s) } 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)); @@ -445,14 +474,15 @@ do_mkdir(int fd_in, int fd_out, char *path, Attrib *a) } 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)); @@ -460,45 +490,61 @@ do_rmdir(int fd_in, int fd_out, char *path) } 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 + error("Server version does not support lstat operation"); + return(NULL); + } + + 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)); @@ -507,16 +553,16 @@ do_setstat(int fd_in, int fd_out, char *path, Attrib *a) } 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)); @@ -524,19 +570,20 @@ do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len, } 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); @@ -570,7 +617,7 @@ do_realpath(int fd_in, int fd_out, char *path) } 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; @@ -578,65 +625,71 @@ do_rename(int fd_in, int fd_out, char *oldpath, char *newpath) 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); @@ -669,19 +722,46 @@ do_readlink(int fd_in, int fd_out, char *path) 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; - a = do_stat(fd_in, fd_out, remote_path, 0); + TAILQ_INIT(&requests); + + a = do_stat(conn, remote_path, 0); if (a == NULL) return(-1); @@ -697,134 +777,203 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path, 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); + send_msg(conn->fd_out, &msg); debug3("Sent message SSH2_FXP_OPEN I:%d 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, (u_int64_t)offset, COPY_SIZE); + /* Send some more requests */ + while (num_req < max_req) { + debug3("Request range %llu -> %llu (%d/%d)", + offset, 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:%d I:%d 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", req->offset, + req->offset + len - 1); + if (len > req->len) + fatal("Received more data than asked for " + "%d > %d", 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)", req->offset + len, + 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) { + 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)", + offset, num_req); + max_req = 1; + } + else if (max_req < conn->num_requests + 1) { + ++max_req; + } + } + break; + default: fatal("Expected SSH2_FXP_DATA(%d) packet, got %d", 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, - (u_int64_t)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 */ + /* 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) + if (pflag && fchmod(local_fd, mode) == -1) #else - if (pflag && chmod(local_path, mode) == -1) + 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)); + 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", @@ -848,85 +997,121 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path, 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); + send_msg(conn->fd_out, &msg); debug3("Sent message SSH2_FXP_OPEN I:%d 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:%d O:%llu S:%u", + id, (u_int64_t)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, (u_int64_t)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, - (u_int64_t)offset); + if (ack == NULL) + fatal("Unexpected ACK %u", id); + + if (id == startid || len == 0 || + id - ackid >= conn->num_requests) { + buffer_clear(&msg); + get_msg(conn->fd_in, &msg); + type = buffer_get_char(&msg); + 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 != id; + ack = TAILQ_NEXT(ack, tq)) + ; + if (ack == NULL) + fatal("Can't find request for ID %d", 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 %d bytes at %llu", + ack->id, ack->len, 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); } - diff --git a/openssh/sftp-client.h b/openssh/sftp-client.h index a322b25..ceda879 100644 --- a/openssh/sftp-client.h +++ b/openssh/sftp-client.h @@ -1,7 +1,7 @@ -/* $OpenBSD: sftp-client.h,v 1.6 2001/06/26 06:33:01 itojun Exp $ */ +/* $OpenBSD: sftp-client.h,v 1.9 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 @@ -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,55 +41,59 @@ struct SFTP_DIRENT { * Initialiase a SSH filexfer connection. Returns -1 on error or * protocol version on success. */ -int do_init(int, int); +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, int, char *, u_int); +int do_close(struct sftp_conn *, char *, u_int); /* List contents of directory 'path' to stdout */ -int do_ls(int, int, char *); +int do_ls(struct sftp_conn *, char *); /* Read contents of 'path' to NULL-terminated array 'dir' */ -int do_readdir(int, int, char *, SFTP_DIRENT ***); +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 **); /* Delete file 'path' */ -int do_rm(int, int, char *); +int do_rm(struct sftp_conn *, char *); /* Create directory 'path' */ -int do_mkdir(int, int, char *, Attrib *); +int do_mkdir(struct sftp_conn *, char *, Attrib *); /* Remove directory 'path' */ -int do_rmdir(int, int, char *); +int do_rmdir(struct sftp_conn *, char *); /* Get file attributes of 'path' (follows symlinks) */ -Attrib *do_stat(int, int, char *, int); +Attrib *do_stat(struct sftp_conn *, char *, int); /* Get file attributes of 'path' (does not follow symlinks) */ -Attrib *do_lstat(int, int, char *, int); +Attrib *do_lstat(struct sftp_conn *, char *, int); /* Get file attributes of open file 'handle' */ -Attrib *do_fstat(int, int, char *, u_int, int); +Attrib *do_fstat(struct sftp_conn *, char *, u_int, int); /* Set file attributes of 'path' */ -int do_setstat(int, int, char *, Attrib *); +int do_setstat(struct sftp_conn *, char *, Attrib *); /* Set file attributes of open file 'handle' */ -int do_fsetstat(int, int, char *, u_int, Attrib *); +int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); /* Canonicalise 'path' - caller must free result */ -char *do_realpath(int, int, char *); +char *do_realpath(struct sftp_conn *, char *); /* Rename 'oldpath' to 'newpath' */ -int do_rename(int, int, char *, char *); +int do_rename(struct sftp_conn *, char *, char *); /* Rename 'oldpath' to 'newpath' */ -int do_symlink(int, int, char *, char *); +int do_symlink(struct sftp_conn *, char *, char *); /* Return target of symlink 'path' - caller must free result */ -char *do_readlink(int, int, char *); +char *do_readlink(struct sftp_conn *, char *); /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ @@ -94,10 +101,12 @@ char *do_readlink(int, int, char *); * Download 'remote_path' to 'local_path'. Preserve permissions and times * if 'pflag' is set */ -int do_download(int, int, char *, char *, int); +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, int, char *, char *, int); +int do_upload(struct sftp_conn *, char *, char *, int); + +#endif diff --git a/openssh/sftp-common.c b/openssh/sftp-common.c index 9235048..4fb4496 100644 --- a/openssh/sftp-common.c +++ b/openssh/sftp-common.c @@ -24,7 +24,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sftp-common.c,v 1.4 2001/07/14 15:10:17 stevesk Exp $"); +RCSID("$OpenBSD: sftp-common.c,v 1.5 2001/12/02 02:08:32 deraadt Exp $"); #include "buffer.h" #include "bufaux.h" @@ -144,6 +144,6 @@ fx2txt(int status) return("Operation unsupported"); default: return("Unknown status"); - }; + } /* NOTREACHED */ } diff --git a/openssh/sftp-glob.c b/openssh/sftp-glob.c index a432bdf..1234074 100644 --- a/openssh/sftp-glob.c +++ b/openssh/sftp-glob.c @@ -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,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sftp-glob.c,v 1.8 2001/07/14 15:10:17 stevesk Exp $"); +RCSID("$OpenBSD: sftp-glob.c,v 1.10 2002/02/13 00:59:23 djm Exp $"); #include "buffer.h" #include "bufaux.h" @@ -41,18 +41,17 @@ struct SFTP_OPENDIR { }; static struct { - int fd_in; - int fd_out; + struct sftp_conn *conn; } cur; 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; @@ -110,7 +109,7 @@ 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) { @@ -129,12 +128,12 @@ 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); } @@ -142,17 +141,17 @@ 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 = fudge_opendir; @@ -160,11 +159,9 @@ remote_glob(int fd_in, int fd_out, const char *pattern, int flags, 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, errfunc, - pglob)); + return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); } diff --git a/openssh/sftp-glob.h b/openssh/sftp-glob.h index 2885044..488b0a8 100644 --- a/openssh/sftp-glob.h +++ b/openssh/sftp-glob.h @@ -1,7 +1,7 @@ -/* $OpenBSD: sftp-glob.h,v 1.5 2001/06/26 17:27:24 markus Exp $ */ +/* $OpenBSD: sftp-glob.h,v 1.6 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 @@ -26,5 +26,13 @@ /* Remote sftp filename globbing */ +#ifndef _SFTP_GLOB_H +#define _SFTP_GLOB_H + +#include "sftp-client.h" + int -remote_glob(int, int, const char *, int, int (*)(const char *, int), glob_t *); +remote_glob(struct sftp_conn *, const char *, int, + int (*)(const char *, int), glob_t *); + +#endif diff --git a/openssh/sftp-int.c b/openssh/sftp-int.c index 841e562..5de9389 100644 --- a/openssh/sftp-int.c +++ b/openssh/sftp-int.c @@ -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,7 +26,7 @@ /* XXX: recursive operations */ #include "includes.h" -RCSID("$OpenBSD: sftp-int.c,v 1.40 2001/08/14 09:23:02 markus Exp $"); +RCSID("$OpenBSD: sftp-int.c,v 1.44 2002/02/13 00:59:23 djm Exp $"); #include "buffer.h" #include "xmalloc.h" @@ -42,8 +42,11 @@ RCSID("$OpenBSD: sftp-int.c,v 1.40 2001/08/14 09:23:02 markus Exp $"); /* 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" @@ -205,7 +208,7 @@ path_append(char *p1, char *p2) ret = xmalloc(len); strlcpy(ret, p1, len); - if (strcmp(p1, "/") != 0) + if (strcmp(p1, "/") != 0) strlcat(ret, "/", len); strlcat(ret, p2, len); @@ -330,12 +333,12 @@ is_dir(char *path) } static int -remote_is_dir(int in, int out, char *path) +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); @@ -343,7 +346,7 @@ remote_is_dir(int in, int out, char *path) } static int -process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) +process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) { char *abs_src = NULL; char *abs_dst = NULL; @@ -357,7 +360,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) 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 +384,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) 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 +396,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) 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 +408,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) 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; @@ -420,7 +423,7 @@ out: } static int -process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) +process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) { char *tmp_dst = NULL; char *abs_dst = NULL; @@ -446,7 +449,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) 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 +466,19 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) 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 +490,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) 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; } @@ -517,7 +520,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg, 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 */ @@ -645,7 +648,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg, } static int -parse_dispatch_command(int in, int out, const char *cmd, char **pwd) +parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) { char *path1, *path2, *tmp; int pflag, cmdnum, i; @@ -665,32 +668,26 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 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 +696,19 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 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 +731,22 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 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 +777,17 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 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 +797,14 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 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 +814,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 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 +834,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) help(); break; case I_VERSION: - printf("SFTP protocol version %d\n", version); + printf("SFTP protocol version %d\n", sftp_proto_version(conn)); break; default: fatal("%d is not implemented", cmdnum); @@ -863,12 +860,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) 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 +874,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) 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,7 +885,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) snprintf(cmd, sizeof cmd, "get %s %s", dir, file2); - parse_dispatch_command(fd_in, fd_out, cmd, &pwd); + parse_dispatch_command(conn, cmd, &pwd); return; } } @@ -899,7 +897,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) setlinebuf(infile); #endif - for(;;) { + for (;;) { char *cp; printf("sftp> "); @@ -915,7 +913,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) if (cp) *cp = '\0'; - if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd)) + if (parse_dispatch_command(conn, cmd, &pwd)) break; } xfree(pwd); diff --git a/openssh/sftp-int.h b/openssh/sftp-int.h index 699e758..9768758 100644 --- a/openssh/sftp-int.h +++ b/openssh/sftp-int.h @@ -1,7 +1,7 @@ -/* $OpenBSD: sftp-int.h,v 1.4 2001/06/26 17:27:25 markus 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 diff --git a/openssh/sftp-server.c b/openssh/sftp-server.c index 2ef9753..117e6cc 100644 --- a/openssh/sftp-server.c +++ b/openssh/sftp-server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001 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.30 2001/07/31 12:42:50 jakob Exp $"); +RCSID("$OpenBSD: sftp-server.c,v 1.33 2002/02/13 00:28:13 markus Exp $"); #include "buffer.h" #include "bufaux.h" @@ -144,7 +144,7 @@ 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; } @@ -153,7 +153,7 @@ 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; @@ -589,6 +589,11 @@ process_setstat(void) name = get_string(NULL); a = get_attrib(); TRACE("setstat id %d 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) @@ -626,6 +631,11 @@ process_fsetstat(void) 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); @@ -771,7 +781,7 @@ process_readdir(void) } 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); } @@ -897,7 +907,7 @@ process_readlink(void) send_status(id, errno_to_portable(errno)); else { Stat s; - + link[len] = '\0'; attrib_clear(&s.attrib); s.name = s.long_name = link; @@ -951,7 +961,7 @@ process(void) if (buffer_len(&iqueue) < 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 "); diff --git a/openssh/sftp.1 b/openssh/sftp.1 index 0cc4e2b..2faaff1 100644 --- a/openssh/sftp.1 +++ b/openssh/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.26 2001/09/17 20:38:09 stevesk Exp $ +.\" $OpenBSD: sftp.1,v 1.33 2002/02/26 19:06:43 deraadt Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -30,11 +30,14 @@ .Nd Secure file transfer program .Sh SYNOPSIS .Nm sftp -.Op Fl 1Cv +.Op Fl vC1 .Op Fl b Ar batchfile -.Op Fl F Ar ssh_config .Op Fl o Ar ssh_option .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 @@ -63,8 +66,6 @@ The last usage format allows the sftp client to start in a remote directory. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl 1 -Specify the use of protocol version 1. .It Fl b Ar batchfile Batch mode reads a series of commands from an input .Ar batchfile @@ -75,19 +76,10 @@ non-interactive authentication. .Nm will abort if any of the following commands fail: -.Ic get , put , rename , ln , rm , mkdir , chdir , lchdir +.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 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 o Ar ssh_option Can be used to pass options to .Nm ssh @@ -105,6 +97,33 @@ 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 @@ -112,8 +131,8 @@ to use for the encrypted connection. The program must understand .Xr ssh 1 options. -.It Fl v -Raise logging level. This option is also passed to ssh. +.It Fl 1 +Specify the use of protocol version 1. .El .Sh INTERACTIVE COMMANDS Once in interactive mode, diff --git a/openssh/sftp.c b/openssh/sftp.c index 06110f9..045e076 100644 --- a/openssh/sftp.c +++ b/openssh/sftp.c @@ -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,9 +24,8 @@ #include "includes.h" -RCSID("$OpenBSD: sftp.c,v 1.21 2001/09/19 19:24:19 stevesk Exp $"); +RCSID("$OpenBSD: sftp.c,v 1.26 2002/02/12 12:32:27 djm Exp $"); -/* XXX: commandline mode */ /* XXX: short-form remote directory listings (like 'ls -C') */ #include "buffer.h" @@ -46,11 +45,12 @@ extern char *__progname; char *__progname; #endif -char *ssh_program = _PATH_SSH_PROGRAM; FILE* infile; +size_t copy_buffer_len = 32768; +size_t num_requests = 16; static void -connect_to_server(char **args, int *in, int *out, pid_t *sshpid) +connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid) { int c_in, c_out; #ifdef USE_PIPES @@ -81,8 +81,8 @@ connect_to_server(char **args, int *in, int *out, pid_t *sshpid) 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); } @@ -93,9 +93,12 @@ connect_to_server(char **args, int *in, int *out, pid_t *sshpid) static void usage(void) { + extern char *__progname; + fprintf(stderr, - "usage: sftp [-1Cv] [-b batchfile] [-F config] [-o option] [-s subsystem|path]\n" - " [-S program] [user@]host[:file [file]]\n"); + "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); } @@ -107,6 +110,7 @@ main(int argc, char **argv) char *host, *userhost, *cp, *file2; 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; @@ -114,7 +118,7 @@ main(int argc, char **argv) __progname = get_progname(argv[0]); args.list = NULL; - addargs(&args, "ssh"); /* overwritten with ssh_program */ + addargs(&args, "ssh"); /* overwritten with ssh_program */ addargs(&args, "-oFallBackToRsh no"); addargs(&args, "-oForwardX11 no"); addargs(&args, "-oForwardAgent no"); @@ -122,7 +126,7 @@ main(int argc, char **argv) ll = SYSLOG_LEVEL_INFO; infile = stdin; /* Read from STDIN unless changed by -b */ - while ((ch = getopt(argc, argv, "1hvCo:s:S:b:F:")) != -1) { + while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { switch (ch) { case 'C': addargs(&args, "-C"); @@ -157,54 +161,78 @@ main(int argc, char **argv) } 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(); + if (sftp_direct == NULL) { + if (optind == argc || argc > (optind + 2)) + usage(); - userhost = xstrdup(argv[optind]); - file2 = argv[optind+1]; + userhost = xstrdup(argv[optind]); + file2 = argv[optind+1]; - if ((cp = colon(userhost)) != NULL) { - *cp++ = '\0'; - file1 = cp; - } + if ((cp = colon(userhost)) != NULL) { + *cp++ = '\0'; + file1 = cp; + } - if ((host = strchr(userhost, '@')) == NULL) - host = userhost; - else { - *host++ = '\0'; - if (!userhost[0]) { - fprintf(stderr, "Missing username\n"); - usage(); + if ((host = strchr(userhost, '@')) == NULL) + host = userhost; + else { + *host++ = '\0'; + if (!userhost[0]) { + fprintf(stderr, "Missing username\n"); + usage(); + } + addargs(&args, "-l%s",userhost); } - addargs(&args, "-l%s",userhost); - } - host = cleanhostname(host); - if (!*host) { - fprintf(stderr, "Missing hostname\n"); - usage(); - } + host = cleanhostname(host); + if (!*host) { + fprintf(stderr, "Missing hostname\n"); + usage(); + } - log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); - addargs(&args, "-oProtocol %d", sshver); + log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); + addargs(&args, "-oProtocol %d", sshver); - /* no subsystem if the server-spec contains a '/' */ - if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) - addargs(&args, "-s"); + /* 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; + 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); + 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"); - connect_to_server(args.list, &in, &out, &sshpid); + fprintf(stderr, "Attaching to %s...\n", sftp_direct); + connect_to_server(sftp_direct, args.list, &in, &out, + &sshpid); + } interactive_loop(in, out, file1, file2); diff --git a/openssh/sftp.h b/openssh/sftp.h index 2ad9586..675c608 100644 --- a/openssh/sftp.h +++ b/openssh/sftp.h @@ -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 diff --git a/openssh/ssh-add.1 b/openssh/ssh-add.1 index b842080..41d5def 100644 --- a/openssh/ssh-add.1 +++ b/openssh/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.27 2001/08/23 18:08:59 stevesk Exp $ +.\" $OpenBSD: ssh-add.1,v 1.30 2002/02/04 20:41:16 stevesk Exp $ .\" .\" -*- nroff -*- .\" @@ -55,7 +55,10 @@ .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, @@ -91,21 +94,16 @@ Remove key in smartcard .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" @@ -132,6 +130,11 @@ may be necessary to redirect the input from .Pa /dev/null to make this work.) .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. diff --git a/openssh/ssh-add.c b/openssh/ssh-add.c index 585b714..b057a08 100644 --- a/openssh/ssh-add.c +++ b/openssh/ssh-add.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-add.c,v 1.46 2001/10/02 08:38:50 djm Exp $"); +RCSID("$OpenBSD: ssh-add.c,v 1.50 2002/01/29 14:27:57 markus Exp $"); #include @@ -58,6 +58,15 @@ char *__progname; /* 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 +}; + + /* we keep a cache of one passphrases */ static char *pass = NULL; static void @@ -90,7 +99,7 @@ delete_file(AuthenticationConnection *ac, const char *filename) key_free(public); xfree(comment); - + return ret; } @@ -160,7 +169,7 @@ add_file(AuthenticationConnection *ac, const char *filename) xfree(comment); key_free(private); - + return ret; } @@ -169,16 +178,16 @@ update_card(AuthenticationConnection *ac, int add, const char *id) { if (ssh_update_card(ac, add, id)) { fprintf(stderr, "Card %s: %s\n", - add ? "added" : "removed", id); + add ? "added" : "removed", id); return 0; } else { fprintf(stderr, "Could not %s card: %s\n", - add ? "add" : "remove", id); + add ? "add" : "remove", id); return -1; } } -static void +static int list_identities(AuthenticationConnection *ac, int do_fp) { Key *key; @@ -188,8 +197,8 @@ list_identities(AuthenticationConnection *ac, int do_fp) 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, @@ -206,8 +215,24 @@ list_identities(AuthenticationConnection *ac, int do_fp) xfree(comment); } } - if (!had_identities) + if (!had_identities) { printf("The agent has no identities.\n"); + return -1; + } + return 0; +} + +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 @@ -231,8 +256,6 @@ main(int argc, char **argv) extern char *optarg; extern int optind; AuthenticationConnection *ac = NULL; - struct passwd *pw; - char buf[1024]; char *sc_reader_id = NULL; int i, ch, deleting = 0, ret = 0; @@ -246,13 +269,14 @@ main(int argc, char **argv) ac = ssh_get_authentication_connection(); if (ac == NULL) { fprintf(stderr, "Could not open a connection to your authentication agent.\n"); - exit(1); + exit(2); } - while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) { + while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) { switch (ch) { case 'l': case 'L': - list_identities(ac, ch == 'l' ? 1 : 0); + if (list_identities(ac, ch == 'l' ? 1 : 0) == -1) + ret = 1; goto done; break; case 'd': @@ -267,7 +291,7 @@ main(int argc, char **argv) sc_reader_id = optarg; break; case 'e': - deleting = 1; + deleting = 1; sc_reader_id = optarg; break; default: @@ -284,30 +308,26 @@ main(int argc, char **argv) goto done; } if (argc == 0) { - pw = getpwuid(getuid()); - if (!pw) { + char buf[MAXPATHLEN]; + struct passwd *pw; + + if ((pw = getpwuid(getuid())) == NULL) { fprintf(stderr, "No user found with uid %u\n", (u_int)getuid()); ret = 1; goto done; } - snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_CLIENT_IDENTITY); - if (deleting) { - if (delete_file(ac, buf) == -1) - ret = 1; - } else { - if (add_file(ac, buf) == -1) + + for(i = 0; default_files[i]; i++) { + snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, + default_files[i]); + if (do_file(ac, deleting, buf) == -1) ret = 1; } } else { - for (i = 0; i < argc; i++) { - if (deleting) { - if (delete_file(ac, argv[i]) == -1) - ret = 1; - } else { - if (add_file(ac, argv[i]) == -1) - ret = 1; - } + for(i = 0; i < argc; i++) { + if (do_file(ac, deleting, argv[i]) == -1) + ret = 1; } } clear_pass(); diff --git a/openssh/ssh-agent.1 b/openssh/ssh-agent.1 index 00c1992..9909ef5 100644 --- a/openssh/ssh-agent.1 +++ b/openssh/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.28 2001/09/05 06:23:07 deraadt Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.31 2002/02/04 20:41:16 stevesk Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -94,9 +94,11 @@ Keys are added using .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 @@ -127,6 +129,11 @@ Later .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 @@ -147,15 +154,6 @@ line terminates. .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 diff --git a/openssh/ssh-agent.c b/openssh/ssh-agent.c index a004e32..555396f 100644 --- a/openssh/ssh-agent.c +++ b/openssh/ssh-agent.c @@ -1,5 +1,3 @@ -/* $OpenBSD: ssh-agent.c,v 1.72 2001/08/03 10:31:30 jakob Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -36,7 +34,13 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.72 2001/08/03 10:31:30 jakob Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.82 2002/03/04 17:27:39 stevesk Exp $"); + +#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) +#include +#else +#include "openbsd-compat/fake-queue.h" +#endif #include #include @@ -46,13 +50,9 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.72 2001/08/03 10:31:30 jakob Exp $"); #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" @@ -61,11 +61,15 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.72 2001/08/03 10:31:30 jakob Exp $"); #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; } SocketEntry; @@ -73,14 +77,15 @@ typedef struct { u_int sockets_alloc = 0; SocketEntry *sockets = NULL; -typedef struct { +typedef struct identity { + TAILQ_ENTRY(identity) next; Key *key; char *comment; } Identity; typedef struct { int nentries; - Identity *identities; + TAILQ_HEAD(idqueue, identity) idlist; } Idtab; /* private key table, one per protocol version */ @@ -105,8 +110,8 @@ 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; } } @@ -121,19 +126,25 @@ idtab_lookup(int version) } /* return matching private key for given public key */ -static 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); +} + +static void +free_identity(Identity *id) +{ + key_free(id->key); + xfree(id->comment); + xfree(id); } /* send list of supported public keys to 'client' */ @@ -142,14 +153,13 @@ process_request_identities(SocketEntry *e, int version) { Idtab *tab = idtab_lookup(version); Buffer msg; - int i; + Identity *id; 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); @@ -172,7 +182,8 @@ process_request_identities(SocketEntry *e, int version) static void process_authentication_challenge1(SocketEntry *e) { - Key *key, *private; + Identity *id; + Key *key; BIGNUM *challenge; int i, len; Buffer msg; @@ -182,7 +193,8 @@ process_authentication_challenge1(SocketEntry *e) 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); @@ -192,13 +204,14 @@ process_authentication_challenge1(SocketEntry *e) /* Only protocol 1.1 is supported */ if (buffer_len(&e->input) == 0) goto failure; - buffer_get(&e->input, (char *) session_id, 16); + buffer_get(&e->input, session_id, 16); response_type = buffer_get_int(&e->input); 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; @@ -239,7 +252,7 @@ static void process_sign_request2(SocketEntry *e) { extern int datafellows; - Key *key, *private; + Key *key; u_char *blob, *data, *signature = NULL; u_int blen, dlen, slen = 0; int flags; @@ -257,9 +270,9 @@ process_sign_request2(SocketEntry *e) 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); @@ -283,13 +296,13 @@ process_sign_request2(SocketEntry *e) static void process_remove_identity(SocketEntry *e, int version) { - Key *key = NULL, *private; + Key *key = NULL; u_char *blob; u_int blen; u_int bits; int success = 0; - switch(version){ + switch (version) { case 1: key = key_new(KEY_RSA1); bits = buffer_get_int(&e->input); @@ -307,9 +320,8 @@ process_remove_identity(SocketEntry *e, int version) 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 @@ -318,19 +330,12 @@ process_remove_identity(SocketEntry *e, int version) * 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; } @@ -344,13 +349,14 @@ process_remove_identity(SocketEntry *e, int version) 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. */ @@ -391,7 +397,7 @@ process_add_identity(SocketEntry *e, int version) type_name = buffer_get_string(&e->input, 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); @@ -424,14 +430,11 @@ process_add_identity(SocketEntry *e, int version) 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; + if (lookup_identity(k, version) == NULL) { + Identity *id = xmalloc(sizeof(Identity)); + id->key = k; + id->comment = comment; + TAILQ_INSERT_TAIL(&tab->idlist, id, next); /* Increment the number of identities. */ tab->nentries++; } else { @@ -453,7 +456,7 @@ process_add_smartcard_key (SocketEntry *e) Key *n = NULL, *k = NULL; char *sc_reader_id = NULL; int success = 0; - + sc_reader_id = buffer_get_string(&e->input, NULL); k = sc_get_key(sc_reader_id); xfree(sc_reader_id); @@ -466,36 +469,28 @@ process_add_smartcard_key (SocketEntry *e) tab = idtab_lookup(1); k->type = KEY_RSA1; - if (lookup_private_key(k, NULL, 1) == NULL) { - if (tab->nentries == 0) - tab->identities = xmalloc(sizeof(Identity)); - else - tab->identities = xrealloc(tab->identities, - (tab->nentries + 1) * sizeof(Identity)); + if (lookup_identity(k, 1) == NULL) { + Identity *id = xmalloc(sizeof(Identity)); 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_engine()); - tab->identities[tab->nentries].key = n; - tab->identities[tab->nentries].comment = - xstrdup("rsa1 smartcard"); + id->key = n; + id->comment = xstrdup("rsa1 smartcard"); + TAILQ_INSERT_TAIL(&tab->idlist, id, next); tab->nentries++; } k->type = KEY_RSA; tab = idtab_lookup(2); - if (lookup_private_key(k, NULL, 2) == NULL) { - if (tab->nentries == 0) - tab->identities = xmalloc(sizeof(Identity)); - else - tab->identities = xrealloc(tab->identities, - (tab->nentries + 1) * sizeof(Identity)); + if (lookup_identity(k, 2) == NULL) { + Identity *id = xmalloc(sizeof(Identity)); 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_engine()); - tab->identities[tab->nentries].key = n; - tab->identities[tab->nentries].comment = - xstrdup("rsa smartcard"); + id->key = n; + id->comment = xstrdup("rsa smartcard"); + TAILQ_INSERT_TAIL(&tab->idlist, id, next); tab->nentries++; } key_free(k); @@ -508,8 +503,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { - Key *k = NULL, *private; - int idx; + Key *k = NULL; int success = 0; char *sc_reader_id = NULL; @@ -520,25 +514,22 @@ process_remove_smartcard_key(SocketEntry *e) if (k == NULL) { error("sc_get_pubkey failed"); } else { + Identity *id; k->type = KEY_RSA1; - private = lookup_private_key(k, &idx, 1); - if (private != NULL) { + id = lookup_identity(k, 1); + if (id != NULL) { Idtab *tab = idtab_lookup(1); - key_free(tab->identities[idx].key); - xfree(tab->identities[idx].comment); - if (idx != tab->nentries) - tab->identities[idx] = tab->identities[tab->nentries]; + TAILQ_REMOVE(&tab->idlist, id, next); + free_identity(id); tab->nentries--; success = 1; } k->type = KEY_RSA; - private = lookup_private_key(k, &idx, 2); - if (private != NULL) { + id = lookup_identity(k, 2); + if (id != NULL) { Idtab *tab = idtab_lookup(2); - key_free(tab->identities[idx].key); - xfree(tab->identities[idx].comment); - if (idx != tab->nentries) - tab->identities[idx] = tab->identities[tab->nentries]; + TAILQ_REMOVE(&tab->idlist, id, next); + free_identity(id); tab->nentries--; success = 1; } @@ -561,7 +552,7 @@ process_message(SocketEntry *e) u_char *cp; 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); @@ -611,10 +602,10 @@ process_message(SocketEntry *e) #ifdef SMARTCARD case SSH_AGENTC_ADD_SMARTCARD_KEY: process_add_smartcard_key(e); - break; + break; case SSH_AGENTC_REMOVE_SMARTCARD_KEY: process_remove_smartcard_key(e); - break; + break; #endif /* SMARTCARD */ default: /* Unknown message. Respond with failure. */ @@ -627,7 +618,7 @@ process_message(SocketEntry *e) } static void -new_socket(int type, int fd) +new_socket(sock_type type, int fd) { u_int i, old_alloc; if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) @@ -728,7 +719,8 @@ after_select(fd_set *readset, fd_set *writeset) 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); @@ -782,7 +774,7 @@ after_select(fd_set *readset, fd_set *writeset) } static void -cleanup_socket(void) +cleanup_socket(void *p) { if (socket_name[0]) unlink(socket_name); @@ -793,14 +785,14 @@ cleanup_socket(void) static void cleanup_exit(int i) { - cleanup_socket(); + cleanup_socket(NULL); exit(i); } static void cleanup_handler(int sig) { - cleanup_socket(); + cleanup_socket(NULL); _exit(2); } @@ -971,7 +963,7 @@ main(int ac, char **av) pid = fork(); if (pid == -1) { perror("fork"); - exit(1); + cleanup_exit(1); } if (pid != 0) { /* Parent - execute the given command. */ close(sock); @@ -994,9 +986,11 @@ main(int ac, char **av) perror(av[0]); exit(1); } + /* child */ + log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); if (setsid() == -1) { - perror("setsid"); + error("setsid: %s", strerror(errno)); cleanup_exit(1); } @@ -1009,16 +1003,13 @@ main(int ac, char **av) /* 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"); + error("setrlimit RLIMIT_CORE: %s", strerror(errno)); cleanup_exit(1); } #endif skip: - if (atexit(cleanup_socket) < 0) { - perror("atexit"); - cleanup_exit(1); - } + fatal_add_cleanup(cleanup_socket, NULL); new_socket(AUTH_SOCKET, sock); if (ac > 0) { signal(SIGALRM, check_parent_exists); @@ -1037,7 +1028,7 @@ skip: 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); } diff --git a/openssh/ssh-dss.c b/openssh/ssh-dss.c index 9f3a287..02403f5 100644 --- a/openssh/ssh-dss.c +++ b/openssh/ssh-dss.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-dss.c,v 1.9 2001/11/07 22:10:28 markus Exp $"); +RCSID("$OpenBSD: ssh-dss.c,v 1.14 2002/02/28 15:46:33 markus Exp $"); #include #include @@ -42,13 +42,13 @@ RCSID("$OpenBSD: ssh-dss.c,v 1.9 2001/11/07 22:10:28 markus Exp $"); int ssh_dss_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) { DSA_SIG *sig; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; - u_char *digest, *ret, sigblob[SIGBLOB_LEN]; + u_char *ret, digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; u_int rlen, slen, len, dlen; Buffer b; @@ -56,16 +56,13 @@ ssh_dss_sign( 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)); - memset(digest, 0, dlen); - xfree(digest); if (sig == NULL) { error("ssh_dss_sign: sign failed"); return -1; @@ -109,13 +106,13 @@ ssh_dss_sign( int ssh_dss_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) { DSA_SIG *sig; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; - u_char *digest, *sigblob; + u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen; int rlen, ret; Buffer b; @@ -145,7 +142,7 @@ ssh_dss_verify( sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); - if(rlen != 0) { + if (rlen != 0) { error("ssh_dss_verify: " "remaining bytes in signature %d", rlen); xfree(sigblob); @@ -158,9 +155,12 @@ ssh_dss_verify( } /* 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); @@ -170,16 +170,13 @@ ssh_dss_verify( } /* 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); debug("ssh_dss_verify: signature %s", diff --git a/openssh/ssh-dss.h b/openssh/ssh-dss.h index 0613acb..94961b1 100644 --- a/openssh/ssh-dss.h +++ b/openssh/ssh-dss.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.h,v 1.5 2001/06/26 17:27:25 markus 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,7 +26,7 @@ #ifndef DSA_H #define DSA_H -int ssh_dss_sign(Key *, u_char **, int *, u_char *, int); -int ssh_dss_verify(Key *, u_char *, int, u_char *, int); +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 diff --git a/openssh/ssh-keygen.1 b/openssh/ssh-keygen.1 index 622cb5c..6ad94e6 100644 --- a/openssh/ssh-keygen.1 +++ b/openssh/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.50 2001/10/25 21:14:32 markus Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.53 2002/02/16 14:53:37 stevesk 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 @@ -86,10 +86,11 @@ 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 instead creates 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 @@ -111,10 +112,14 @@ The program also asks for a passphrase. 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 character, and provides very bad -passphrases). +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. @@ -198,8 +203,6 @@ for protocol version 1 and 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 diff --git a/openssh/ssh-keygen.c b/openssh/ssh-keygen.c index 6d50997..6aff4a4 100644 --- a/openssh/ssh-keygen.c +++ b/openssh/ssh-keygen.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keygen.c,v 1.83 2001/10/25 21:14:32 markus Exp $"); +RCSID("$OpenBSD: ssh-keygen.c,v 1.94 2002/02/25 16:33:27 markus Exp $"); #include #include @@ -73,8 +73,7 @@ int convert_to_ssh2 = 0; 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 @@ -91,21 +90,25 @@ 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); @@ -147,7 +150,7 @@ static void do_convert_to_ssh2(struct passwd *pw) { Key *k; - int len; + u_int len; u_char *blob; struct stat st; @@ -188,12 +191,12 @@ buffer_get_bignum_bits(Buffer *b, BIGNUM *value) 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); } static Key * -do_convert_private_ssh2_from_blob(u_char *blob, int blen) +do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) { Buffer b; Key *key = NULL; @@ -272,7 +275,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, int blen) 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); @@ -333,7 +336,7 @@ do_convert_from_ssh2(struct passwd *pw) *p = '\0'; strlcat(encoded, line, sizeof(encoded)); } - blen = uudecode(encoded, (u_char *)blob, sizeof(blob)); + blen = uudecode(encoded, blob, sizeof(blob)); if (blen < 0) { fprintf(stderr, "uudecode failed.\n"); exit(1); @@ -355,7 +358,8 @@ do_convert_from_ssh2(struct passwd *pw) exit(1); } key_free(k); - fprintf(stdout, "\n"); + if (!private) + fprintf(stdout, "\n"); fclose(fp); exit(0); } @@ -393,7 +397,7 @@ do_print_public(struct passwd *pw) debug("#bytes %d", len); \ if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \ goto done; \ - } while(0) + } while (0) static int get_AUT0(char *aut0) @@ -534,7 +538,9 @@ 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; @@ -668,7 +674,7 @@ do_change_passphrase(struct passwd *pw) read_passphrase("Enter new passphrase (empty for no " "passphrase): ", RP_ALLOW_STDIN); passphrase2 = read_passphrase("Enter same passphrase again: ", - RP_ALLOW_STDIN); + RP_ALLOW_STDIN); /* Verify that they are the same. */ if (strcmp(passphrase1, passphrase2) != 0) { @@ -746,7 +752,7 @@ do_change_comment(struct passwd *pw) 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) { @@ -833,7 +839,7 @@ usage(void) 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; @@ -845,8 +851,6 @@ main(int ac, char **av) extern char *optarg; __progname = get_progname(av[0]); - init_rng(); - seed_rng(); SSLeay_add_all_algorithms(); @@ -962,8 +966,14 @@ main(int ac, char **av) #endif /* SMARTCARD */ } + init_rng(); + seed_rng(); arc4random_stir(); + 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); diff --git a/openssh/ssh-keyscan.1 b/openssh/ssh-keyscan.1 index 17f7340..2f33ddf 100644 --- a/openssh/ssh-keyscan.1 +++ b/openssh/ssh-keyscan.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.12 2001/09/05 06:23:07 deraadt Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.14 2002/02/13 08:33:47 mpech Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -104,7 +104,7 @@ Print the host key for machine .Pa hostname : .Bd -literal -ssh-keyscan hostname +$ ssh-keyscan hostname .Ed .Pp Find all hosts from the file @@ -112,7 +112,7 @@ Find all hosts from the file which have new or different keys from those in the sorted file .Pa ssh_known_hosts : .Bd -literal -ssh-keyscan -t rsa,dsa -f ssh_hosts | \e\ +$ ssh-keyscan -t rsa,dsa -f ssh_hosts | \e\ sort -u - ssh_known_hosts | diff ssh_known_hosts - .Ed .Sh FILES @@ -138,7 +138,7 @@ is either 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 if the server is older than version 2.9. diff --git a/openssh/ssh-keyscan.c b/openssh/ssh-keyscan.c index 3fbe88d..824264c 100644 --- a/openssh/ssh-keyscan.c +++ b/openssh/ssh-keyscan.c @@ -7,7 +7,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keyscan.c,v 1.30 2001/10/08 19:05:05 markus Exp $"); +RCSID("$OpenBSD: ssh-keyscan.c,v 1.35 2002/03/04 18:30:23 stevesk Exp $"); #if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) #include @@ -493,8 +493,9 @@ static void congreet(int s) { 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); @@ -510,26 +511,32 @@ congreet(int s) 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'; + 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) { - int remote_major, remote_minor; - char remote_version[sizeof buf]; - - if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) == 3) - compat_datafellows(remote_version); - else - datafellows = 0; 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", @@ -647,6 +654,8 @@ do_host(char *host) char *name = strnnsep(&host, " \t\n"); int j; + if (name == NULL) + return; for (j = KT_RSA1; j <= KT_RSA; j *= 2) { if (get_keytypes & j) { while (ncon >= MAXCON) @@ -656,11 +665,17 @@ do_host(char *host) } } -static void -fatal_callback(void *arg) +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 @@ -673,9 +688,9 @@ usage(void) 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"); + 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); } @@ -742,7 +757,7 @@ main(int argc, char **argv) get_keytypes |= KT_RSA; break; case KEY_UNSPEC: - fatal("unknown key type %s\n", tname); + fatal("unknown key type %s", tname); } tname = strtok(NULL, ","); } @@ -762,7 +777,6 @@ main(int argc, char **argv) usage(); log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); - fatal_add_cleanup(fatal_callback, NULL); maxfd = fdlim_get(1); if (maxfd < 0) diff --git a/openssh/ssh-rand-helper.c b/openssh/ssh-rand-helper.c new file mode 100644 index 0000000..28ea659 --- /dev/null +++ b/openssh/ssh-rand-helper.c @@ -0,0 +1,809 @@ +/* + * 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; +} + +int +main(int argc, char **argv) +{ + unsigned char buf[OUTPUT_SEED_SIZE]; + int ret; + + __progname = get_progname(argv[0]); + /* XXX: need some debugging mode */ + log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + +#ifdef USE_SEED_FILES + prng_read_seedfile(); +#endif + + /* + * Seed the RNG from wherever we can + */ + + /* Take whatever is on the stack, but don't credit it */ + RAND_add(buf, sizeof(buf), 0); + + debug("Seeded RNG with %i bytes from system calls", + (int)stir_from_system()); + +#ifdef PRNGD_PORT + if (get_random_bytes_prngd(buf, sizeof(buf), PRNGD_PORT, NULL) == -1) + fatal("Entropy collection failed"); + RAND_add(buf, sizeof(buf), sizeof(buf)); +#elif defined(PRNGD_SOCKET) + if (get_random_bytes_prngd(buf, sizeof(buf), 0, PRNGD_SOCKET) == -1) + fatal("Entropy collection failed"); + RAND_add(buf, sizeof(buf), sizeof(buf)); +#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, sizeof(buf)); + + ret = atomicio(write, STDOUT_FILENO, buf, sizeof(buf)); + + memset(buf, '\0', sizeof(buf)); + + return ret == sizeof(buf) ? 0 : 1; +} + diff --git a/openssh/ssh-rsa.c b/openssh/ssh-rsa.c index a6a703b..8e79d4e 100644 --- a/openssh/ssh-rsa.c +++ b/openssh/ssh-rsa.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-rsa.c,v 1.13 2001/11/10 13:22:42 markus Exp $"); +RCSID("$OpenBSD: ssh-rsa.c,v 1.16 2002/02/24 19:14:59 markus Exp $"); #include #include @@ -40,12 +40,12 @@ RCSID("$OpenBSD: ssh-rsa.c,v 1.13 2001/11/10 13:22:42 markus Exp $"); int ssh_rsa_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) { 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; @@ -63,18 +63,15 @@ ssh_rsa_sign( 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(); @@ -113,14 +110,14 @@ ssh_rsa_sign( int ssh_rsa_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) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; - u_char *sigblob, *digest; + u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen; int rlen, ret, nid; @@ -150,7 +147,7 @@ ssh_rsa_verify( sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); - if(rlen != 0) { + if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); xfree(sigblob); return -1; @@ -161,15 +158,12 @@ ssh_rsa_verify( 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) { diff --git a/openssh/ssh-rsa.h b/openssh/ssh-rsa.h index 11d355d..7177a3f 100644 --- a/openssh/ssh-rsa.h +++ b/openssh/ssh-rsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.h,v 1.5 2001/06/26 17:27:25 markus 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,7 +26,7 @@ #ifndef SSH_RSA_H #define SSH_RSA_H -int ssh_rsa_sign(Key *, u_char **, int *, u_char *, int); -int ssh_rsa_verify(Key *, u_char *, int, u_char *, int); +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 diff --git a/openssh/ssh.1 b/openssh/ssh.1 index ad3c960..43b75dc 100644 --- a/openssh/ssh.1 +++ b/openssh/ssh.1 @@ -34,7 +34,7 @@ .\" (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.141 2001/11/08 17:49:53 markus Exp $ +.\" $OpenBSD: ssh.1,v 1.148 2002/02/18 17:55:20 markus Exp $ .Dd September 25, 1999 .Dt SSH 1 .Os @@ -126,7 +126,7 @@ or .Pa /etc/shosts.equiv , and if additionally the server can verify the client's host key (see -.Pa /etc/ssh_known_hosts +.Pa /etc/ssh/ssh_known_hosts and .Pa $HOME/.ssh/known_hosts in the @@ -207,8 +207,8 @@ the password cannot be seen by someone listening on the network. .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 hostbased method; @@ -365,7 +365,7 @@ Host keys are stored in .Pa $HOME/.ssh/known_hosts in the user's home directory. Additionally, the file -.Pa /etc/ssh_known_hosts +.Pa /etc/ssh/ssh_known_hosts is automatically checked for known hosts. Any new hosts are automatically added to the user's file. If a host's identification @@ -443,11 +443,15 @@ something like .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 @@ -517,7 +521,6 @@ for older servers. .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 applications (eg. sftp). The @@ -570,7 +573,7 @@ option below. 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_config +.Pq Pa /etc/ssh/ssh_config will be ignored. The default for the per-user configuration file is .Pa $HOME/.ssh/config . @@ -645,7 +648,7 @@ the following order: command line options, user's configuration file .Pq Pa $HOME/.ssh/config , and system-wide configuration file -.Pq Pa /etc/ssh_config . +.Pq Pa /etc/ssh/ssh_config . For each parameter, the first obtained value will be used. The configuration files contain sections bracketed by @@ -883,7 +886,7 @@ The default is .It Cm GlobalKnownHostsFile Specifies a file to use for the global host key database instead of -.Pa /etc/ssh_known_hosts . +.Pa /etc/ssh/ssh_known_hosts . .It Cm HostbasedAuthentication Specifies whether to try rhosts based authentication with public key authentication. @@ -900,7 +903,7 @@ is similar to 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 +.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 @@ -915,10 +918,14 @@ 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 +Specifies a file from which the user's RSA or DSA authentication identity +is read. 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. Additionally, any identities represented by the authentication agent will be used for authentication. The file name may use the tilde @@ -927,7 +934,7 @@ 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 +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. @@ -942,8 +949,7 @@ 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. +.Dq no . .It Cm KerberosAuthentication Specifies whether Kerberos authentication will be used. The argument to this keyword must be @@ -971,8 +977,9 @@ Only the superuser can forward privileged ports. 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. +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. @@ -1013,7 +1020,7 @@ authentication methods. This allows a client to prefer one method (e.g. over another method (e.g. .Cm password ) The default for this option is: -.Dq hostbased,publickey,keyboard-interactive,password +.Dq hostbased,publickey,keyboard-interactive,password . .It Cm Protocol Specifies the protocol versions .Nm @@ -1137,7 +1144,7 @@ will never automatically add host keys to the 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_known_hosts +.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 @@ -1305,7 +1312,7 @@ to the environment. .It Pa $HOME/.ssh/known_hosts Records host keys for all hosts the user has logged into that are not in -.Pa /etc/ssh_known_hosts . +.Pa /etc/ssh/ssh_known_hosts . See .Xr sshd 8 . .It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa @@ -1360,7 +1367,7 @@ In the simplest form the format is the same as the .pub 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 /etc/ssh_known_hosts +.It Pa /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared by the system administrator to contain the public host keys of all machines in the @@ -1383,13 +1390,13 @@ to verify the client host when logging in; other names are needed because does not convert the user-supplied name to a canonical name before checking the key, because someone with access to the name servers would then be able to fool host authentication. -.It Pa /etc/ssh_config +.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. -.It Pa /etc/ssh_host_key, /etc/ssh_host_dsa_key, /etc/ssh_host_rsa_key +.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 @@ -1424,7 +1431,7 @@ Note that by default will be installed so that it requires successful RSA host authentication before permitting \s+2.\s0rhosts authentication. If the server machine does not have the client's host key in -.Pa /etc/ssh_known_hosts , +.Pa /etc/ssh/ssh_known_hosts , it can be stored in .Pa $HOME/.ssh/known_hosts . The easiest way to do this is to @@ -1461,7 +1468,7 @@ This file is processed exactly as This file may be useful to permit logins using .Nm but not using rsh/rlogin. -.It Pa /etc/sshrc +.It Pa /etc/ssh/sshrc Commands in this file are executed by .Nm when the user logs in just before the user's shell (or command) is started. @@ -1481,6 +1488,10 @@ Contains additional definitions for environment variables, see section .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. diff --git a/openssh/ssh.c b/openssh/ssh.c index 2984a59..117a093 100644 --- a/openssh/ssh.c +++ b/openssh/ssh.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.149 2001/10/24 08:51:35 markus Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $"); #include #include @@ -485,7 +485,7 @@ again: fwd_host_port); else if (opt == 'R') add_remote_forward(&options, fwd_port, buf, - fwd_host_port); + fwd_host_port); break; case 'D': @@ -787,19 +787,36 @@ again: } static void -x11_get_proto(char *proto, int proto_len, char *data, int data_len) +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, "%.100s list unix:%s 2>" + _PATH_DEVNULL, options.xauth_location, display+10); + else + snprintf(line, sizeof line, "%.100s 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); @@ -815,11 +832,11 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len) 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; } } @@ -837,7 +854,7 @@ ssh_init_forwarding(void) 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, @@ -876,7 +893,6 @@ static int ssh_session(void) { int type; - int plen; int interactive = 0; int have_tty = 0; struct winsize ws; @@ -894,7 +910,7 @@ ssh_session(void) 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) @@ -932,7 +948,7 @@ ssh_session(void) 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; @@ -943,15 +959,15 @@ ssh_session(void) } /* 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) { @@ -971,8 +987,8 @@ ssh_session(void) 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."); } @@ -993,7 +1009,7 @@ ssh_session(void) 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(); @@ -1011,7 +1027,7 @@ ssh_session(void) } static void -client_subsystem_reply(int type, int plen, void *ctxt) +client_subsystem_reply(int type, u_int32_t seq, void *ctxt) { int id, len; @@ -1019,10 +1035,10 @@ client_subsystem_reply(int type, int plen, void *ctxt) 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); } /* request pty/x11/agent/tcpfwd/shell for channel */ @@ -1059,9 +1075,9 @@ ssh_session2_setup(int id, void *arg) } 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); @@ -1081,24 +1097,23 @@ ssh_session2_setup(int id, void *arg) 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 */ 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); } @@ -1130,24 +1145,20 @@ ssh_session2_open(void) window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; - if (!tty_flag) { - window *= 2; - packetmax *=2; + if (tty_flag) { + window >>= 1; + packetmax >>= 1; } c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"), /*nonblock*/0); - if (c == NULL) - fatal("ssh_session2_open: channel_new failed"); debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); if (!no_shell_flag) - channel_register_callback(c->self, - SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, - ssh_session2_setup, (void *)0); + channel_register_confirm(c->self, ssh_session2_setup); return c->self; } diff --git a/openssh/ssh.h b/openssh/ssh.h index 383c7fe..fdf554d 100644 --- a/openssh/ssh.h +++ b/openssh/ssh.h @@ -1,3 +1,5 @@ +/* $OpenBSD: ssh.h,v 1.64 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -10,8 +12,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: ssh.h,v 1.63 2001/05/24 18:57:53 stevesk Exp $"); */ - #ifndef SSH_H #define SSH_H diff --git a/openssh/ssh2.h b/openssh/ssh2.h index e45aef2..091e52b 100644 --- a/openssh/ssh2.h +++ b/openssh/ssh2.h @@ -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 */ diff --git a/openssh/ssh_config b/openssh/ssh_config index 6209354..a8a8d72 100644 --- a/openssh/ssh_config +++ b/openssh/ssh_config @@ -1,8 +1,9 @@ -# $OpenBSD: ssh_config,v 1.10 2001/04/03 21:19:38 todd Exp $ +# $OpenBSD: ssh_config,v 1.12 2002/01/16 17:55:33 stevesk 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(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. # Configuration data is parsed as follows: # 1. command line options @@ -17,7 +18,7 @@ # Host * # ForwardAgent no # ForwardX11 no -# RhostsAuthentication no +# RhostsAuthentication yes # RhostsRSAAuthentication yes # RSAAuthentication yes # PasswordAuthentication yes @@ -25,11 +26,12 @@ # 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 2,1 -# Cipher blowfish +# Cipher 3des +# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc # EscapeChar ~ diff --git a/openssh/sshconnect.c b/openssh/sshconnect.c index de6cc22..5bb50e0 100644 --- a/openssh/sshconnect.c +++ b/openssh/sshconnect.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.115 2001/10/08 19:05:05 markus Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.119 2002/01/21 15:13:51 markus Exp $"); #include @@ -31,6 +31,7 @@ RCSID("$OpenBSD: sshconnect.c,v 1.115 2001/10/08 19:05:05 markus Exp $"); #include "readconf.h" #include "atomicio.h" #include "misc.h" +#include "readpass.h" char *client_version_string = NULL; char *server_version_string = NULL; @@ -49,15 +50,15 @@ sockaddr_ntop(struct sockaddr *sa) static char addrbuf[INET6_ADDRSTRLEN]; switch (sa->sa_family) { - case AF_INET: - addr = &((struct sockaddr_in *)sa)->sin_addr; - break; - case AF_INET6: - addr = &((struct sockaddr_in6 *)sa)->sin6_addr; - break; - default: - /* This case should be protected against elsewhere */ - abort(); + case AF_INET: + addr = &((struct sockaddr_in *)sa)->sin_addr; + break; + case AF_INET6: + addr = &((struct sockaddr_in6 *)sa)->sin6_addr; + break; + default: + /* This case should be protected against elsewhere */ + abort(); /* XXX abort is bad -- do something else */ } inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); return addrbuf; @@ -109,7 +110,7 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw, /* 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); @@ -258,7 +259,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, int full_failure = 1; debug("ssh_connect: getuid %u geteuid %u anon %d", - (u_int) getuid(), (u_int) geteuid(), anonymous); + (u_int) getuid(), (u_int) geteuid(), anonymous); /* Get default port if port has not been set. */ if (port == 0) { @@ -340,7 +341,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, * which connect() has already returned an * error. */ - shutdown(sock, SHUT_RDWR); close(sock); } } @@ -429,12 +429,12 @@ ssh_exchange_identification(void) &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) && @@ -489,40 +489,24 @@ ssh_exchange_identification(void) 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); - fprintf(stderr, "%s", prompt); - while (1) { - if (fgets(buf, sizeof(buf), f) == NULL) { - fprintf(stderr, "\n"); - strlcpy(buf, "no", sizeof buf); - } - /* Remove newline from response. */ - if (strchr(buf, '\n')) - *strchr(buf, '\n') = 0; - if (strcmp(buf, "yes") == 0) - retval = 1; - else if (strcmp(buf, "no") == 0) - retval = 0; - else - fprintf(stderr, "Please type 'yes' or 'no': "); - - 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; } } @@ -544,7 +528,8 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 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; /* @@ -559,7 +544,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, switch (hostaddr->sa_family) { case AF_INET: local = (ntohl(((struct sockaddr_in *)hostaddr)-> - sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; + sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; salen = sizeof(struct sockaddr_in); break; case AF_INET6: @@ -621,7 +606,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, */ host_file = user_hostfile; host_status = check_host_in_hostfile(host_file, host, host_key, - file_key, &host_line); + file_key, &host_line); if (host_status == HOST_NEW) { host_file = system_hostfile; host_status = check_host_in_hostfile(host_file, host, host_key, @@ -664,7 +649,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, "'%.128s' not in list of known hosts.", type, ip); else if (!add_host_to_hostfile(user_hostfile, ip, - host_key)) + 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); @@ -689,18 +674,16 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 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), + 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); xfree(fp); - if (!confirm(prompt)) { + if (!confirm(msg)) goto fail; - } } if (options.check_host_ip && ip_status == HOST_NEW) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); @@ -790,7 +773,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, error("Port forwarding is disabled to avoid " "man-in-the-middle attacks."); options.num_local_forwards = - options.num_remote_forwards = 0; + options.num_remote_forwards = 0; } /* * XXX Should permit the user to change to use the new id. @@ -804,20 +787,28 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 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) { + log(msg); error("Exiting, you have requested strict checking."); goto fail; } else if (options.strict_host_key_checking == 2) { - if (!confirm("Are you sure you want " - "to continue connecting (yes/no)? ")) { + strlcat(msg, "\nAre you sure you want " + "to continue connecting (yes/no)? ", sizeof(msg)); + if (!confirm(msg)) goto fail; - } + } else { + log(msg); } } diff --git a/openssh/sshconnect1.c b/openssh/sshconnect1.c index d6b8623..d7722f4 100644 --- a/openssh/sshconnect1.c +++ b/openssh/sshconnect1.c @@ -13,10 +13,10 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.41 2001/10/06 11:18:19 markus Exp $"); +RCSID("$OpenBSD: sshconnect1.c,v 1.48 2002/02/11 16:15:46 markus Exp $"); #include -#include +#include #ifdef KRB4 #include @@ -67,7 +67,6 @@ try_agent_authentication(void) AuthenticationConnection *auth; u_char response[16]; u_int i; - int plen, clen; Key *key; BIGNUM *challenge; @@ -76,12 +75,12 @@ try_agent_authentication(void) 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); @@ -94,7 +93,7 @@ try_agent_authentication(void) 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. */ @@ -108,9 +107,8 @@ try_agent_authentication(void) 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."); @@ -135,7 +133,7 @@ try_agent_authentication(void) 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) { @@ -210,7 +208,7 @@ try_rsa_authentication(int idx) BIGNUM *challenge; Key *public, *private; char buf[300], *passphrase, *comment, *authfile; - int i, type, quit, plen, clen; + int i, type, quit; public = options.identity_keys[idx]; authfile = options.identity_files[idx]; @@ -225,7 +223,7 @@ try_rsa_authentication(int idx) packet_write_wait(); /* 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 @@ -241,10 +239,10 @@ try_rsa_authentication(int idx) 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."); @@ -292,7 +290,7 @@ try_rsa_authentication(int idx) packet_write_wait(); /* Expect the server to reject it... */ - packet_read_expect(&plen, SSH_SMSG_FAILURE); + packet_read_expect(SSH_SMSG_FAILURE); BN_clear_free(challenge); return 0; } @@ -308,7 +306,7 @@ try_rsa_authentication(int idx) 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; @@ -328,7 +326,6 @@ 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."); @@ -342,7 +339,7 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) 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 +352,10 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) 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 +366,7 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) 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; @@ -389,7 +386,7 @@ try_krb4_authentication(void) 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; @@ -400,10 +397,10 @@ try_krb4_authentication(void) /* Don't do anything if we don't have any tickets. */ if (stat(tkt_string(), &st) < 0) return 0; - + strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)), INST_SZ); - + realm = (char *)krb_realmofhost(get_canonical_hostname(1)); if (!realm) { debug("Kerberos v4: no realm for %s", get_canonical_hostname(1)); @@ -411,7 +408,7 @@ try_krb4_authentication(void) } /* This can really be anything. */ checksum = (u_long)getpid(); - + r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum); if (r != KSUCCESS) { debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]); @@ -424,22 +421,22 @@ try_krb4_authentication(void) return 0; } des_key_sched((des_cblock *) cred.session, schedule); - + /* Send authentication info to server. */ packet_start(SSH_CMSG_AUTH_KERBEROS); packet_put_string((char *) auth.dat, auth.length); packet_send(); packet_write_wait(); - + /* Zero the buffer. */ (void) memset(auth.dat, 0, MAX_KTXT_LEN); - + slen = sizeof(local); memset(&local, 0, sizeof(local)); if (getsockname(packet_get_connection_in(), (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(), @@ -448,25 +445,25 @@ try_krb4_authentication(void) 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."); return 0; break; - + case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ debug("Kerberos v4 authentication accepted."); - + /* Get server's response. */ reply = packet_get_string((u_int *) &auth.length); 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 * key, and the decrypted checksum fails to match, he's @@ -483,7 +480,7 @@ try_krb4_authentication(void) memcpy((char *)&cksum, (char *)msg_data.app_data, sizeof(cksum)); cksum = ntohl(cksum); - + /* If it matches, we're golden. */ if (cksum == checksum + 1) { debug("Kerberos v4 challenge successful."); @@ -491,7 +488,7 @@ try_krb4_authentication(void) } else packet_disconnect("Kerberos v4 challenge failed!"); break; - + default: packet_disconnect("Protocol error on Kerberos v4 response: %d", type); } @@ -510,29 +507,29 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) krb5_ccache ccache = NULL; const char *remotehost; krb5_data ap; - int type, payload_len; + 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; } - + 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", @@ -540,9 +537,9 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) 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) { @@ -551,48 +548,47 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) 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); + + 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_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) { + /* 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); @@ -600,76 +596,76 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) krb5_free_ap_rep_enc_part(*context, reply); if (ap.length > 0) krb5_data_free(&ap); - + return (ret); } static void send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) { - int fd, type, payload_len; + int fd, type; krb5_error_code problem; krb5_data outbuf; krb5_ccache ccache = NULL; krb5_creds creds; krb5_kdc_flags flags; const char *remotehost; - + 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; - + 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); - + remotehost = get_canonical_hostname(1); - + 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); - + + 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", @@ -692,45 +688,45 @@ send_krb4_tgt(void) CREDENTIALS *creds; struct stat st; char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; - int problem, type, len; - + int problem, type; + /* Don't do anything if we don't have any tickets. */ if (stat(tkt_string(), &st) < 0) return; - + creds = xmalloc(sizeof(*creds)); - + 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)) { problem = RD_AP_EXP; goto out; } creds_to_radix(creds, (u_char *)buffer, sizeof(buffer)); - + packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); packet_put_cstring(buffer); packet_send(); packet_write_wait(); - - type = packet_read(&len); - + + type = packet_read(); + 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."); - + xfree(creds); return; - + out: debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]); xfree(creds); @@ -745,7 +741,7 @@ send_afs_tokens(void) int i, type, len; char buf[2048], *p, *server_cell; char buffer[8192]; - + /* Move over ktc_GetToken, here's something leaner. */ for (i = 0; i < 100; i++) { /* just in case */ parms.in = (char *) &i; @@ -755,7 +751,7 @@ send_afs_tokens(void) if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) break; p = buf; - + /* Get secret token. */ memcpy(&creds.ticket_st.length, p, sizeof(u_int)); if (creds.ticket_st.length > MAX_KTXT_LEN) @@ -763,7 +759,7 @@ send_afs_tokens(void) p += sizeof(u_int); memcpy(creds.ticket_st.dat, p, creds.ticket_st.length); p += creds.ticket_st.length; - + /* Get clear token. */ memcpy(&len, p, sizeof(len)); if (len != sizeof(struct ClearToken)) @@ -773,7 +769,7 @@ send_afs_tokens(void) p += len; p += sizeof(len); /* primary flag */ server_cell = p; - + /* Flesh out our credentials. */ strlcpy(creds.service, "afs", sizeof(creds.service)); creds.instance[0] = '\0'; @@ -785,7 +781,7 @@ send_afs_tokens(void) 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) @@ -797,8 +793,8 @@ send_afs_tokens(void) /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */ - type = packet_read(&len); - + type = packet_read(); + if (type == SSH_SMSG_FAILURE) debug("AFS token for cell %s rejected.", server_cell); else if (type != SSH_SMSG_SUCCESS) @@ -816,7 +812,6 @@ static int try_challenge_response_authentication(void) { int type, i; - int payload_len; u_int clen; char prompt[1024]; char *challenge, *response; @@ -829,7 +824,7 @@ try_challenge_response_authentication(void) packet_send(); packet_write_wait(); - type = packet_read(&payload_len); + type = packet_read(); if (type != SSH_SMSG_FAILURE && type != SSH_SMSG_AUTH_TIS_CHALLENGE) { packet_disconnect("Protocol error: got %d in response " @@ -840,9 +835,9 @@ try_challenge_response_authentication(void) return 0; } challenge = packet_get_string(&clen); - packet_integrity_check(payload_len, (4 + clen), type); + packet_check_eom(); snprintf(prompt, sizeof prompt, "%s%s", challenge, - strchr(challenge, '\n') ? "" : "\nResponse: "); + strchr(challenge, '\n') ? "" : "\nResponse: "); xfree(challenge); if (i != 0) error("Permission denied, please try again."); @@ -860,7 +855,7 @@ try_challenge_response_authentication(void) 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) @@ -877,7 +872,7 @@ try_challenge_response_authentication(void) static int try_password_authentication(char *prompt) { - int type, i, payload_len; + int type, i; char *password; debug("Doing password authentication."); @@ -894,7 +889,7 @@ try_password_authentication(char *prompt) 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) @@ -912,54 +907,43 @@ ssh_kex(char *host, struct sockaddr *hostaddr) { 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; - - rbits = BN_num_bits(public_key->n); + 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(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; - - rbits = BN_num_bits(host_key->n); + 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->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); @@ -972,21 +956,17 @@ ssh_kex(char *host, struct sockaddr *hostaddr) 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)); - - 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; - if (verify_host_key(host, hostaddr, &k) == -1) + BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); + + 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(); @@ -1008,7 +988,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr) * 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); @@ -1022,35 +1003,35 @@ ssh_kex(char *host, struct sockaddr *hostaddr) * 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)) @@ -1064,7 +1045,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) /* 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)); @@ -1099,7 +1080,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) * 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."); } @@ -1116,8 +1097,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, 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"); @@ -1132,21 +1112,21 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, * 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) goto success; if (type != SSH_SMSG_FAILURE) 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) { + options.kerberos_authentication) { debug("Trying Kerberos v5 authentication."); - + if (try_krb5_authentication(&context, &auth_context)) { - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) @@ -1154,14 +1134,14 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, } } #endif /* KRB5 */ - + #ifdef KRB4 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && options.kerberos_authentication) { debug("Trying Kerberos v4 authentication."); - + if (try_krb4_authentication()) { - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) @@ -1169,7 +1149,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, } } #endif /* KRB4 */ - + /* * Use rhosts authentication if running in privileged socket and we * do not wish to remain anonymous. @@ -1183,7 +1163,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, packet_write_wait(); /* The server should respond with success or failure. */ - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) @@ -1254,7 +1234,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, 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)) && diff --git a/openssh/sshconnect2.c b/openssh/sshconnect2.c index 3107885..c5b5ee5 100644 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@ -23,26 +23,18 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.85 2001/11/07 16:03:17 markus Exp $"); - -#include -#include -#include -#include +RCSID("$OpenBSD: sshconnect2.c,v 1.97 2002/02/25 16:33:27 markus 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 "dh.h" @@ -111,7 +103,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) 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 */ @@ -146,7 +138,7 @@ typedef struct Authmethod Authmethod; 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; @@ -174,20 +166,20 @@ struct Authmethod { 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); +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 *); -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); +int userauth_none(Authctxt *); +int userauth_pubkey(Authctxt *); +int userauth_passwd(Authctxt *); +int userauth_kbdint(Authctxt *); +int userauth_hostbased(Authctxt *); -void userauth(Authctxt *authctxt, char *authlist); +void userauth(Authctxt *, char *); static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); static void clear_auth_state(Authctxt *); @@ -226,7 +218,6 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, { Authctxt authctxt; int type; - int plen; if (options.challenge_response_authentication) options.kbd_interactive_authentication = 1; @@ -236,18 +227,18 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, 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) @@ -308,13 +299,13 @@ userauth(Authctxt *authctxt, char *authlist) } } 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"); @@ -325,7 +316,7 @@ input_userauth_banner(int type, int plen, void *ctxt) 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) @@ -336,7 +327,7 @@ input_userauth_success(int type, int plen, void *ctxt) 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 +338,7 @@ input_userauth_failure(int type, int plen, void *ctxt) authlist = packet_get_string(NULL); partial = packet_get_char(); - packet_done(); + packet_check_eom(); if (partial != 0) log("Authenticated with partial success."); @@ -357,13 +348,15 @@ input_userauth_failure(int type, int plen, void *ctxt) 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,7 +372,7 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) 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", pkalg, blen, authctxt->last_key, authctxt->last_key_hint); @@ -390,7 +383,7 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) 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 +391,12 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) 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 +406,7 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) } sent = sign_and_send_pubkey(authctxt, key, authctxt->last_key_sign); - } while(0); + } while (0); if (key != NULL) key_free(key); @@ -446,7 +445,7 @@ userauth_passwd(Authctxt *authctxt) 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: ", @@ -483,7 +482,7 @@ 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; @@ -568,7 +567,7 @@ 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"); @@ -613,7 +612,7 @@ load_identity_file(char *filename) 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) { @@ -635,8 +634,8 @@ load_identity_file(char *filename) } static int -identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { Key *private; int idx, ret; @@ -646,7 +645,7 @@ identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, return -1; /* private key is stored in external hardware */ - if (options.identity_keys[idx]->flags & KEY_FLAG_EXT) + 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]); @@ -658,15 +657,15 @@ identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, } static int -agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +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); } static int -key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +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); } @@ -710,7 +709,7 @@ userauth_pubkey(Authctxt *authctxt) 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]; @@ -768,7 +767,7 @@ userauth_kbdint(Authctxt *authctxt) * 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; @@ -815,7 +814,7 @@ input_userauth_info_req(int type, int plen, void *ctxt) xfree(response); xfree(prompt); } - packet_done(); /* done with parsing incoming message. */ + packet_check_eom(); /* done with parsing incoming message. */ packet_add_padding(64); packet_send(); @@ -957,7 +956,7 @@ 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) @@ -992,22 +991,23 @@ authmethod_get(char *authlist) } } - -#define DELIM "," - 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; } diff --git a/openssh/sshd.8 b/openssh/sshd.8 index 5a6624b..13d80e3 100644 --- a/openssh/sshd.8 +++ b/openssh/sshd.8 @@ -34,7 +34,7 @@ .\" (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.154 2001/11/07 22:12:01 markus Exp $ +.\" $OpenBSD: sshd.8,v 1.170 2002/02/28 20:46:10 stevesk Exp $ .Dd September 25, 1999 .Dt SSHD 8 .Os @@ -49,6 +49,7 @@ .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 .Sh DESCRIPTION @@ -197,7 +198,7 @@ will send the output to the standard error instead of the system log. .It Fl f Ar configuration_file Specifies the name of the configuration file. The default is -.Pa /etc/sshd_config . +.Pa /etc/ssh/sshd_config . .Nm refuses to start if there is no configuration file. .It Fl g Ar login_grace_time @@ -207,12 +208,18 @@ If the client fails to authenticate the user within 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_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 @@ -237,9 +244,16 @@ it becomes impossible to recover the key for decrypting intercepted communications even if the machine is cracked into or physically seized. A value of zero indicates that the key will never be regenerated. +.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. @@ -248,7 +262,7 @@ 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 +This is useful for updating .Nm reliably as configuration options may change. .It Fl u Ar len @@ -279,6 +293,11 @@ Authentication mechanisms that may require DNS include 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 @@ -297,7 +316,7 @@ to use IPv6 addresses only. .Sh CONFIGURATION FILE .Nm reads configuration data from -.Pa /etc/sshd_config +.Pa /etc/ssh/sshd_config (or the file specified with .Fl f on the command line). @@ -315,7 +334,7 @@ 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 +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. @@ -325,7 +344,7 @@ and 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 regardless of the group list. +By default, login is allowed for all groups. .Pp .It Cm AllowTcpForwarding Specifies whether TCP forwarding is permitted. @@ -336,7 +355,7 @@ 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 +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. @@ -346,7 +365,7 @@ and 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 regardless of the user name. +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. @@ -364,7 +383,7 @@ After expansion, is taken to be an absolute path or one relative to the user's home directory. The default is -.Dq .ssh/authorized_keys +.Dq .ssh/authorized_keys . .It Cm Banner In some jurisdictions, sending a warning message before authentication may be relevant for getting legal protection. @@ -383,7 +402,11 @@ The default is 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. +.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, @@ -417,20 +440,20 @@ The default value is 3. If is left 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 +This keyword can be followed by a list of group name patterns, separated by spaces. -Users whose primary group or supplementary group list matches -one of the patterns aren't allowed to log in. +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 regardless of the group list. +By default, login is allowed for all groups. .Pp .It Cm DenyUsers -This keyword can be followed by a number of user names, separated +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 \&* @@ -438,7 +461,10 @@ 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 regardless of the user name. +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. @@ -467,9 +493,15 @@ 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_host_key ) -used by SSH protocol versions 1 and 2. +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 will refuse to use a file if it is group/world-accessible. @@ -509,7 +541,7 @@ or The default is .Dq no . .It Cm KeepAlive -Specifies whether the system should send keepalive messages to the +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. @@ -524,12 +556,11 @@ users and consuming server resources. The default is .Dq yes (to send keepalives), and the server will notice -if the network goes down or the client host reboots. +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 -in both the server and the client configuration files. +.Dq no . .It Cm KerberosAuthentication Specifies whether Kerberos authentication is allowed. This can be in the form of a Kerberos ticket, or if @@ -612,9 +643,10 @@ The default is 600 (seconds). 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 +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. @@ -741,14 +773,6 @@ 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 /etc/hosts.equiv files is sufficient. @@ -816,6 +840,14 @@ will be disabled because does not know how to handle .Xr xauth 1 cookies. +.It Cm VerifyReverseMapping +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 X11DisplayOffset Specifies the first display number available for .Nm sshd Ns 's @@ -833,6 +865,31 @@ 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 +should bind the X11 forwarding server to the loopback address or to +the wildcard address. By default, +.Nm +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 @@ -917,7 +974,7 @@ Changes to user's home directory. If .Pa $HOME/.ssh/rc exists, runs it; else if -.Pa /etc/sshrc +.Pa /etc/ssh/sshrc exists, runs it; otherwise runs xauth. The @@ -1054,7 +1111,7 @@ command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hu 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_known_hosts , +.Pa /etc/ssh/ssh_known_hosts , and .Pa $HOME/.ssh/known_hosts files contain host public keys for all known hosts. @@ -1079,7 +1136,7 @@ pattern on the line. .Pp Bits, exponent, and modulus are taken directly from the RSA host key; they can be obtained, e.g., from -.Pa /etc/ssh_host_key.pub . +.Pa /etc/ssh/ssh_host_key.pub . The optional comment field continues to the end of the line, and is not used. .Pp Lines starting with @@ -1101,7 +1158,7 @@ Note that the lines in these files are typically hundreds of characters long, and you definitely don't want to type in the host keys by hand. Rather, generate them by a script or by taking -.Pa /etc/ssh_host_key.pub +.Pa /etc/ssh/ssh_host_key.pub and adding the host names at the front. .Ss Examples .Bd -literal @@ -1110,19 +1167,19 @@ cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....= .Ed .Sh FILES .Bl -tag -width Ds -.It Pa /etc/sshd_config +.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. -.It Pa /etc/ssh_host_key, /etc/ssh_host_dsa_key, /etc/ssh_host_rsa_key +.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 accessible to others. Note that .Nm does not start if this file is group/world-accessible. -.It Pa /etc/ssh_host_key.pub, /etc/ssh_host_dsa_key.pub, /etc/ssh_host_rsa_key.pub +.It Pa /etc/ssh/ssh_host_key.pub, /etc/ssh/ssh_host_dsa_key.pub, /etc/ssh/ssh_host_rsa_key.pub These three files contain the public parts of the host keys. These files should be world-readable but writable only by root. @@ -1155,7 +1212,7 @@ and/or .Pa id_rsa.pub files into this file, as described in .Xr ssh-keygen 1 . -.It Pa "/etc/ssh_known_hosts" and "$HOME/.ssh/known_hosts" +.It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts" These files are consulted when using rhosts with RSA host authentication or protocol version 2 hostbased authentication to check the public key of the host. @@ -1163,7 +1220,7 @@ 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_hosts +.Pa /etc/ssh/ssh_known_hosts should be world-readable, and .Pa $HOME/.ssh/known_hosts can but need not be world-readable. @@ -1271,13 +1328,13 @@ something similar to: .Ed .Pp If this file does not exist, -.Pa /etc/sshrc +.Pa /etc/ssh/sshrc is run, and if that does not exist either, xauth is used to store the cookie. .Pp This file should be writable only by the user, and need not be readable by anyone else. -.It Pa /etc/sshrc +.It Pa /etc/ssh/sshrc Like .Pa $HOME/.ssh/rc . This can be used to specify diff --git a/openssh/sshd.c b/openssh/sshd.c index 71a5c2c..ea92932 100644 --- a/openssh/sshd.c +++ b/openssh/sshd.c @@ -40,11 +40,11 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.209 2001/11/10 13:19:45 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $"); #include #include -#include +#include #include "ssh.h" #include "ssh1.h" @@ -169,11 +169,11 @@ struct { * 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 a signal is received. */ -int received_sighup = 0; -int received_sigterm = 0; +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]; @@ -185,6 +185,10 @@ int session_id2_len = 0; /* 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 */ + /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); @@ -203,6 +207,16 @@ close_listen_socks(void) 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 @@ -211,8 +225,11 @@ close_listen_socks(void) static void sighup_handler(int sig) { + int save_errno = errno; + received_sighup = 1; signal(SIGHUP, sighup_handler); + errno = save_errno; } /* @@ -224,6 +241,7 @@ 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)); exit(1); @@ -381,7 +399,7 @@ sshd_exchange_identification(int sock_in, int sock_out) 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); @@ -392,7 +410,7 @@ sshd_exchange_identification(int sock_in, int sock_out) } mismatch = 0; - switch(remote_major) { + switch (remote_major) { case 1: if (remote_minor == 99) { if (options.protocol & SSH_PROTO_2) @@ -449,7 +467,7 @@ destroy_sensitive_data(void) 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; @@ -462,33 +480,37 @@ destroy_sensitive_data(void) 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; } static 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; @@ -525,8 +547,30 @@ drop_connection(int startups) 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. @@ -564,7 +608,7 @@ main(int ac, char **av) initialize_server_options(&options); /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqtQ46")) != -1) { + while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) { switch (opt) { case '4': IPv4or6 = AF_INET; @@ -646,27 +690,15 @@ main(int ac, char **av) 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, " -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"); - exit(1); + usage(); + break; } } SSLeay_add_all_algorithms(); @@ -677,8 +709,10 @@ main(int ac, char **av) * 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 @@ -706,14 +740,14 @@ main(int ac, char **av) /* 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) { @@ -722,7 +756,7 @@ main(int ac, char **av) 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; @@ -814,7 +848,7 @@ main(int ac, char **av) /* Chdir to the root directory so that the current disk can be unmounted if desired. */ chdir("/"); - + /* ignore SIGPIPE */ signal(SIGPIPE, SIG_IGN); @@ -866,11 +900,11 @@ main(int ac, char **av) * 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); @@ -963,7 +997,7 @@ main(int ac, char **av) error("select: %.100s", strerror(errno)); if (received_sigterm) { log("Received signal %d; terminating.", - received_sigterm); + (int) received_sigterm); close_listen_socks(); unlink(options.pid_file); exit(255); @@ -1002,6 +1036,7 @@ main(int ac, char **av) } if (fcntl(newsock, F_SETFL, 0) < 0) { error("newsock del O_NONBLOCK: %s", strerror(errno)); + close(newsock); continue; } if (drop_connection(startups) == 1) { @@ -1055,9 +1090,7 @@ main(int ac, char **av) * 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; @@ -1117,11 +1150,11 @@ main(int ac, char **av) /* 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)); @@ -1174,8 +1207,9 @@ main(int ac, char **av) * 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 %d not trusted.", remote_port); options.rhosts_authentication = 0; @@ -1224,7 +1258,6 @@ 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]; @@ -1308,7 +1341,7 @@ do_ssh1_kex(void) 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(); @@ -1325,13 +1358,13 @@ do_ssh1_kex(void) 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_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY); + packet_check_eom(); /* * Decrypt it using our private server key and private host key (key @@ -1401,7 +1434,7 @@ do_ssh1_kex(void) } 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"); diff --git a/openssh/sshd_config b/openssh/sshd_config index e1a052a..3eb1987 100644 --- a/openssh/sshd_config +++ b/openssh/sshd_config @@ -1,80 +1,92 @@ -# $OpenBSD: sshd_config,v 1.42 2001/09/20 20:57:51 mouring Exp $ - -# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin +# $OpenBSD: sshd_config,v 1.48 2002/02/19 02:50:59 deraadt Exp $ # This is the sshd server system-wide configuration file. See sshd(8) # 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. + +#Port 22 #Protocol 2,1 #ListenAddress 0.0.0.0 #ListenAddress :: # HostKey for protocol version 1 -HostKey /etc/ssh_host_key +#HostKey /etc/ssh/ssh_host_key # HostKeys for protocol version 2 -HostKey /etc/ssh_host_rsa_key -HostKey /etc/ssh_host_dsa_key +#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 +#KeyRegenerationInterval 3600 +#ServerKeyBits 768 # Logging -SyslogFacility AUTH -LogLevel INFO #obsoletes QuietMode and FascistLogging +#SyslogFacility AUTH +#LogLevel INFO # Authentication: -LoginGraceTime 600 -PermitRootLogin yes -StrictModes yes +#LoginGraceTime 600 +#PermitRootLogin yes +#StrictModes yes -RSAAuthentication yes -PubkeyAuthentication yes -#AuthorizedKeysFile %h/.ssh/authorized_keys +#RSAAuthentication yes +#PubkeyAuthentication yes +#AuthorizedKeysFile .ssh/authorized_keys # rhosts authentication should not be used -RhostsAuthentication no +#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_known_hosts -RhostsRSAAuthentication no +#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 -# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication -#IgnoreUserKnownHosts 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 - -# Uncomment to disable s/key passwords -#ChallengeResponseAuthentication no +#PasswordAuthentication yes +#PermitEmptyPasswords no -# Uncomment to enable PAM keyboard-interactive authentication -# Warning: enabling this may bypass the setting of 'PasswordAuthentication' -#PAMAuthenticationViaKbdInt yes +# Change to no to disable s/key passwords +#ChallengeResponseAuthentication yes -# To change Kerberos options -#KerberosAuthentication no +# Kerberos options +# KerberosAuthentication automatically enabled if keyfile exists +#KerberosAuthentication yes #KerberosOrLocalPasswd yes -#AFSTokenPassing no -#KerberosTicketCleanup no +#KerberosTicketCleanup yes + +# AFSTokenPassing automatically enabled if k_hasafs() is true +#AFSTokenPassing yes -# Kerberos TGT Passing does only work with the AFS kaserver -#KerberosTgtPassing yes +# Kerberos TGT Passing only works with the AFS kaserver +#KerberosTgtPassing no + +# Set this to 'yes' to enable PAM keyboard-interactive authentication +# Warning: enabling this may bypass the setting of 'PasswordAuthentication' +#PAMAuthenticationViaKbdInt yes -X11Forwarding no -X11DisplayOffset 10 -PrintMotd yes -#PrintLastLog no -KeepAlive yes +#X11Forwarding no +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PrintMotd yes +#PrintLastLog yes +#KeepAlive yes #UseLogin no -#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 diff --git a/openssh/sshlogin.c b/openssh/sshlogin.c index b7558b9..78c51ab 100644 --- a/openssh/sshlogin.c +++ b/openssh/sshlogin.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshlogin.c,v 1.2 2001/03/24 16:43:27 stevesk Exp $"); +RCSID("$OpenBSD: sshlogin.c,v 1.3 2001/12/19 07:18:56 deraadt Exp $"); #include "loginrec.h" @@ -67,7 +67,7 @@ get_last_login_time(uid_t uid, const char *logname, 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) { struct logininfo *li; @@ -94,11 +94,11 @@ record_utmp_only(pid_t pid, const char *ttyname, const char *user, /* 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) { struct logininfo *li; - li = login_alloc_entry(pid, NULL, NULL, ttyname); + li = login_alloc_entry(pid, user, NULL, ttyname); login_logout(li); login_free_entry(li); } diff --git a/openssh/sshlogin.h b/openssh/sshlogin.h index 79d42a9..bd30278 100644 --- a/openssh/sshlogin.h +++ b/openssh/sshlogin.h @@ -17,7 +17,12 @@ void record_login(pid_t, const char *, const char *, uid_t, const char *, struct sockaddr *); -void record_logout(pid_t, const char *); +void record_logout(pid_t, const char *, const char *); u_long get_last_login_time(uid_t, const char *, char *, u_int); +#ifdef LOGIN_NEEDS_UTMPX +void record_utmp_only(pid_t, const char *, const char *, const char *, + struct sockaddr *); +#endif + #endif diff --git a/openssh/sshpty.c b/openssh/sshpty.c index e1e6031..71c48b5 100644 --- a/openssh/sshpty.c +++ b/openssh/sshpty.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshpty.c,v 1.3 2001/07/22 21:32:27 markus Exp $"); +RCSID("$OpenBSD: sshpty.c,v 1.4 2001/12/19 07:18:56 deraadt Exp $"); #ifdef HAVE_UTIL_H # include @@ -156,7 +156,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) *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; } @@ -328,7 +328,7 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname) fd = open(_PATH_TTY, O_WRONLY); if (fd < 0) error("open /dev/tty failed - could not set controlling tty: %.100s", - strerror(errno)); + strerror(errno)); else { close(fd); } @@ -339,7 +339,7 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname) 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; @@ -378,15 +378,15 @@ pty_setowner(struct passwd *pw, const char *ttyname) if (st.st_uid != pw->pw_uid || st.st_gid != gid) { if (chown(ttyname, pw->pw_uid, gid) < 0) { - if (errno == EROFS && + if (errno == EROFS && (st.st_uid == pw->pw_uid || st.st_uid == 0)) error("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); + ttyname, pw->pw_uid, gid, + strerror(errno)); else fatal("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); + ttyname, pw->pw_uid, gid, + strerror(errno)); } } @@ -395,10 +395,10 @@ pty_setowner(struct passwd *pw, const char *ttyname) 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)); } } } diff --git a/openssh/sshpty.h b/openssh/sshpty.h index 4eb479f..df65e28 100644 --- a/openssh/sshpty.h +++ b/openssh/sshpty.h @@ -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,8 +14,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: sshpty.h,v 1.3 2001/06/26 17:27:25 markus Exp $"); */ - #ifndef SSHPTY_H #define SSHPTY_H diff --git a/openssh/sshtty.c b/openssh/sshtty.c index 7849890..5c016f8 100644 --- a/openssh/sshtty.c +++ b/openssh/sshtty.c @@ -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 @@ static int _in_raw_mode = 0; int in_raw_mode(void) { - return _in_raw_mode; + return _in_raw_mode; } struct termios diff --git a/openssh/ttymodes.c b/openssh/ttymodes.c index c0bb0b1..ccc001f 100644 --- a/openssh/ttymodes.c +++ b/openssh/ttymodes.c @@ -43,7 +43,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ttymodes.c,v 1.14 2001/06/24 17:18:31 markus Exp $"); +RCSID("$OpenBSD: ttymodes.c,v 1.16 2001/12/27 20:39:58 markus Exp $"); #include "packet.h" #include "log.h" @@ -396,7 +396,7 @@ tty_parse_modes(int fd, int *n_bytes_ptr) default: debug("Ignoring unsupported tty mode opcode %d (0x%x)", - opcode, opcode); + opcode, opcode); if (!compat20) { /* * SSH1: @@ -422,7 +422,6 @@ tty_parse_modes(int fd, int *n_bytes_ptr) * 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 { diff --git a/openssh/ttymodes.h b/openssh/ttymodes.h index ad980e9..6870592 100644 --- a/openssh/ttymodes.h +++ b/openssh/ttymodes.h @@ -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 diff --git a/openssh/uidswap.c b/openssh/uidswap.c index cc91fcf..bc67d74 100644 --- a/openssh/uidswap.c +++ b/openssh/uidswap.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: uidswap.c,v 1.18 2001/08/08 21:34:19 markus Exp $"); +RCSID("$OpenBSD: uidswap.c,v 1.19 2001/12/19 07:18:56 deraadt Exp $"); #include "log.h" #include "uidswap.h" @@ -67,7 +67,7 @@ temporarily_use_uid(struct passwd *pw) privileged = 1; temporarily_use_uid_effective = 1; - saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups); + saved_egroupslen = getgroups(NGROUPS_MAX, saved_egroups); if (saved_egroupslen < 0) fatal("getgroups: %.100s", strerror(errno)); @@ -76,7 +76,7 @@ temporarily_use_uid(struct passwd *pw) 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)); } diff --git a/openssh/uuencode.c b/openssh/uuencode.c index f3774f1..89fcb08 100644 --- a/openssh/uuencode.c +++ b/openssh/uuencode.c @@ -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,8 +25,7 @@ #include "includes.h" #include "xmalloc.h" #include "uuencode.h" - -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, @@ -50,7 +47,7 @@ uudecode(const char *src, u_char *target, size_t targsize) ; 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); @@ -58,7 +55,7 @@ uudecode(const char *src, u_char *target, size_t targsize) } 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; diff --git a/openssh/uuencode.h b/openssh/uuencode.h index 0067635..682b623 100644 --- a/openssh/uuencode.h +++ b/openssh/uuencode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uuencode.h,v 1.8 2001/06/26 17:27:25 markus Exp $ */ +/* $OpenBSD: uuencode.h,v 1.9 2002/02/25 16:33:27 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -28,5 +28,5 @@ #define UUENCODE_H int uuencode(u_char *, u_int, char *, size_t); int uudecode(const char *, u_char *, size_t); -void dump_base64(FILE *, u_char *, int); +void dump_base64(FILE *, u_char *, u_int); #endif diff --git a/openssh/version.h b/openssh/version.h index 804e560..529bd67 100644 --- a/openssh/version.h +++ b/openssh/version.h @@ -1,3 +1,4 @@ -/* $OpenBSD: version.h,v 1.25 2001/10/15 16:10:50 deraadt Exp $ */ +/* $OpenBSD: version.h,v 1.28 2002/03/06 00:25:55 markus Exp $ */ + +#define SSH_VERSION "OpenSSH_3.1p1" -#define SSH_VERSION "OpenSSH_3.0.2p1" diff --git a/openssh/xmalloc.h b/openssh/xmalloc.h index e14d014..338a2d2 100644 --- a/openssh/xmalloc.h +++ b/openssh/xmalloc.h @@ -1,3 +1,5 @@ +/* $OpenBSD: xmalloc.h,v 1.8 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -14,8 +16,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: xmalloc.h,v 1.7 2001/06/26 17:27:25 markus Exp $"); */ - #ifndef XMALLOC_H #define XMALLOC_H -- 2.45.2