summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog243
-rw-r--r--Makefile.in20
-rw-r--r--TODO2
-rw-r--r--auth-options.c122
-rw-r--r--auth-pam.c8
-rw-r--r--auth-rh-rsa.c5
-rw-r--r--auth-rhosts.c4
-rw-r--r--auth.c4
-rw-r--r--auth1.c12
-rw-r--r--auth2.c13
-rw-r--r--canohost.c199
-rw-r--r--canohost.h11
-rw-r--r--channels.c12
-rw-r--r--contrib/caldera/openssh.spec4
-rw-r--r--contrib/redhat/openssh.spec4
-rw-r--r--contrib/suse/openssh.spec2
-rw-r--r--scp.13
-rw-r--r--servconf.c12
-rw-r--r--servconf.h3
-rw-r--r--session.c6
-rw-r--r--sftp-client.c792
-rw-r--r--sftp-client.h84
-rw-r--r--sftp-common.c146
-rw-r--r--sftp-common.h55
-rw-r--r--sftp-int.c583
-rw-r--r--sftp-int.h27
-rw-r--r--sftp-server.c102
-rw-r--r--sftp.1156
-rw-r--r--sftp.c222
-rw-r--r--ssh.112
-rw-r--r--ssh_config8
-rw-r--r--sshconnect1.c8
-rw-r--r--sshd.824
-rw-r--r--sshd_config10
34 files changed, 2489 insertions, 429 deletions
diff --git a/ChangeLog b/ChangeLog
index 766c8803..5afaf69a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,9 +2,32 @@
- (bal) I think this is the last of the bsd-*.h that don't belong.
- (bal) Minor Makefile fix
- (bal) openbsd-compat/Makefile minor fix. Ensure dependancies are done
- right.
+ right.
- (bal) Changed order of LIB="" in -with-skey due to library resolving.
- (bal) next-posix.h changed to bsd-nextstep.h
+ - (djm) OpenBSD CVS sync:
+ - markus@cvs.openbsd.org 2001/02/03 03:08:38
+ [auth-options.c auth-rh-rsa.c auth-rhosts.c auth.c canohost.c]
+ [canohost.h servconf.c servconf.h session.c sshconnect1.c sshd.8]
+ [sshd_config]
+ make ReverseMappingCheck optional in sshd_config; ok djm@,dugsong@
+ - markus@cvs.openbsd.org 2001/02/03 03:19:51
+ [ssh.1 sshd.8 sshd_config]
+ Skey is now called ChallengeResponse
+ - markus@cvs.openbsd.org 2001/02/03 03:43:09
+ [sshd.8]
+ use no-pty option in .ssh/authorized_keys* if you need a 8-bit clean
+ channel. note from Erik.Anggard@cygate.se (pr/1659)
+ - stevesk@cvs.openbsd.org 2001/02/03 10:03:06
+ [ssh.1]
+ typos; ok markus@
+ - djm@cvs.openbsd.org 2001/02/04 04:11:56
+ [scp.1 sftp-server.c ssh.1 sshd.8 sftp-client.c sftp-client.h]
+ [sftp-common.c sftp-common.h sftp-int.c sftp-int.h sftp.1 sftp.c]
+ Basic interactive sftp client; ok theo@
+ - (djm) Update RPM specs for new sftp binary
+ - (djm) Update several bits for new optional reverse lookup stuff. I
+ think I got them all.
20010103
- (bal) Cygwin clean up by Corinna Vinschen <vinschen@redhat.com>
@@ -14,7 +37,7 @@
platforms so builds fail. (NeXT being a well known one)
20010102
- - (bal) Makefile fix where sourcedir != builddir by Corinna Vinschen
+ - (bal) Makefile fix where sourcedir != builddir by Corinna Vinschen
<vinschen@redhat.com>
- (bal) Makefile fix to use $(MAKE) instead of 'make' for platforms
that use 'gmake'. Patch by Tim Rice <tim@multitalents.net>
@@ -75,7 +98,7 @@
``StrictHostKeyChecking ask'' documentation and small cleanup.
ok markus@
- stevesk@cvs.openbsd.org 2001/01/28 20:43:25
- [sshd.8]
+ [sshd.8]
spelling. ok markus@
- stevesk@cvs.openbsd.org 2001/01/28 20:53:21
[xmalloc.c]
@@ -94,7 +117,7 @@
- (bal) Minor auth2.c resync. Whitespace and moving of an #include.
20010126
- - (bal) SSH_PROGRAM vs _PATH_SSH_PROGRAM fix pointed out by Roumen
+ - (bal) SSH_PROGRAM vs _PATH_SSH_PROGRAM fix pointed out by Roumen
Petrov <roumen.petrov@skalasoft.com>
- (bal) OpenBSD Sync
- deraadt@cvs.openbsd.org 2001/01/25 8:06:33
@@ -105,12 +128,12 @@
- (djm) Sync bsd-* support files:
- deraadt@cvs.openbsd.org 2000/01/26 03:43:20
[rresvport.c bindresvport.c]
- new bindresvport() semantics that itojun, shin, jean-luc and i have
+ new bindresvport() semantics that itojun, shin, jean-luc and i have
agreed on, which will be happy for the future. bindresvport_sa() for
sockaddr *, too. docs later..
- deraadt@cvs.openbsd.org 2000/01/24 02:24:21
[bindresvport.c]
- in bindresvport(), if sin is non-NULL, example sin->sin_family for
+ in bindresvport(), if sin is non-NULL, example sin->sin_family for
the actual family being processed
- (djm) Mention PRNGd in documentation, it is nicer than EGD
- (djm) Automatically search for "well-known" EGD/PRNGd sockets in autoconf
@@ -124,7 +147,7 @@
- (bal) OpenBSD Resync
- markus@cvs.openbsd.org 2001/01/23 10:45:10
[ssh.h]
- nuke comment
+ nuke comment
- (bal) no 64bit support patch from Tim Rice <tim@multitalents.net>
- (bal) #ifdef around S_IFSOCK if platform does not support it.
patch by Tim Rice <tim@multitalents.net>
@@ -134,7 +157,7 @@
20010123
- (bal) regexp.h typo in configure.in. Should have been regex.h
- (bal) SSH_USER_DIR to _PATH_SSH_USER_DIR patch by stevesk@
- - (bal) SSH_ASKPASS_DEFAULT to _PATH_SSH_ASKPASS_DEFAULT
+ - (bal) SSH_ASKPASS_DEFAULT to _PATH_SSH_ASKPASS_DEFAULT
- (bal) OpenBSD Resync
- markus@cvs.openbsd.org 2001/01/22 8:15:00
[auth-krb4.c sshconnect1.c]
@@ -172,12 +195,12 @@
fix typo; from stevesk@
- markus@cvs.openbsd.org 2001/01/19 16:50:58
[ssh-dss.c]
- clear and free digest, make consistent with other code (use dlen); from
+ clear and free digest, make consistent with other code (use dlen); from
stevesk@
- markus@cvs.openbsd.org 2001/01/20 15:55:20 GMT 2001 by markus
[auth-options.c auth-options.h auth-rsa.c auth2.c]
pass the filename to auth_parse_options()
- - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001
+ - markus@cvs.openbsd.org 2001/01/20 17:59:40 GMT 2001
[readconf.c]
fix SIGSEGV from -o ""; problem noted by jehsom@togetherweb.com
- stevesk@cvs.openbsd.org 2001/01/20 18:20:29
@@ -185,7 +208,7 @@
dh_new_group() does not return NULL. ok markus@
- markus@cvs.openbsd.org 2001/01/20 21:33:42
[ssh-add.c]
- do not loop forever if askpass does not exist; from
+ do not loop forever if askpass does not exist; from
andrew@pimlott.ne.mediaone.net
- djm@cvs.openbsd.org 2001/01/20 23:00:56
[servconf.c]
@@ -207,13 +230,13 @@
match.c misc.c misc.h nchan.c packet.c pty.c radix.h readconf.c
readpass.c readpass.h rsa.c scp.c servconf.c serverloop.c serverloop.h
session.c sftp-server.c ssh-add.c ssh-agent.c ssh-dss.c ssh-keygen.c
- ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h
+ ssh-keyscan.c ssh-rsa.c ssh.c ssh.h sshconnect.c sshconnect.h
sshconnect1.c sshconnect2.c sshd.c tildexpand.c tildexpand.h
ttysmodes.c uidswap.c xmalloc.c]
- split ssh.h and try to cleanup the #include mess. remove unnecessary
+ split ssh.h and try to cleanup the #include mess. remove unnecessary
#includes. rename util.[ch] -> misc.[ch]
- (bal) renamed 'PIDDIR' to '_PATH_SSH_PIDDIR' to match OpenBSD tree
- - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve
+ - (bal) Moved #ifdef KRB4 in auth-krb4.c above the #include to resolve
conflict when compiling for non-kerb install
- (bal) removed the #ifdef SKEY in auth1.c to match Markus' changes
on 1/19.
@@ -233,7 +256,7 @@
- markus@cvs.openbsd.org 2001/01/18 16:20:21
[log-client.c log-server.c log.c readconf.c servconf.c ssh.1 ssh.h
sshd.8 sshd.c]
- log() is at pri=LOG_INFO, since LOG_NOTICE goes to /dev/console on many
+ log() is at pri=LOG_INFO, since LOG_NOTICE goes to /dev/console on many
systems
- markus@cvs.openbsd.org 2001/01/18 16:59:59
[auth-passwd.c auth.c auth.h auth1.c auth2.c serverloop.c session.c
@@ -250,7 +273,7 @@
to fix NULL pointer deref and fake authloop breakage in PAM code.
- (bal) Updated contrib/cygwin/ by Corinna Vinschen <vinschen@redhat.com>
- (bal) Minor cygwin patch to auth1.c. Suggested by djm.
-
+
20010118
- (bal) Super Sized OpenBSD Resync
- markus@cvs.openbsd.org 2001/01/11 22:14:20 GMT 2001 by markus
@@ -272,7 +295,7 @@
[ssh-add.c]
typo, from stevesk@sweden.hp.com
- markus@cvs.openbsd.org 2001/01/13 18:32:50
- [packet.c session.c ssh.c sshconnect.c sshd.c]
+ [packet.c session.c ssh.c sshconnect.c sshd.c]
split out keepalive from packet_interactive (from dale@accentre.com)
set IPTOS_LOWDELAY TCP_NODELAY IPTOS_THROUGHPUT for ssh2, too.
- markus@cvs.openbsd.org 2001/01/13 18:36:45
@@ -284,7 +307,7 @@
- markus@cvs.openbsd.org 2001/01/13 18:43:31
[session.c]
Wall
- - markus@cvs.openbsd.org 2001/01/13 19:14:08
+ - markus@cvs.openbsd.org 2001/01/13 19:14:08
[clientloop.h clientloop.c ssh.c]
move callback to headerfile
- markus@cvs.openbsd.org 2001/01/15 21:40:10
@@ -301,12 +324,12 @@
readable long listing for sftp-server, ok deraadt@
- markus@cvs.openbsd.org 2001/01/16 19:20:06
[key.c ssh-rsa.c]
- make "ssh-rsa" key format for ssh2 confirm to the ietf-drafts; from
- galb@vandyke.com. note that you have to delete older ssh2-rsa keys,
- since they are in the wrong format, too. they must be removed from
+ make "ssh-rsa" key format for ssh2 confirm to the ietf-drafts; from
+ galb@vandyke.com. note that you have to delete older ssh2-rsa keys,
+ since they are in the wrong format, too. they must be removed from
.ssh/authorized_keys2 and .ssh/known_hosts2, etc.
- (cd; grep -v ssh-rsa .ssh/authorized_keys2 > TMP && mv TMP
- .ssh/authorized_keys2) additionally, we now check that
+ (cd; grep -v ssh-rsa .ssh/authorized_keys2 > TMP && mv TMP
+ .ssh/authorized_keys2) additionally, we now check that
BN_num_bits(rsa->n) >= 768.
- markus@cvs.openbsd.org 2001/01/16 20:54:27
[sftp-server.c]
@@ -317,15 +340,15 @@
- (bal) Added bsd-strmode.[ch] since some non-OpenBSD platforms may
be missing such feature.
-
+
20010117
- (djm) Only write random seed file at exit
- (djm) Make PAM support optional, enable with --with-pam
- - (djm) Try to use libcrypt on Linux, but link it after OpenSSL (which
+ - (djm) Try to use libcrypt on Linux, but link it after OpenSSL (which
provides a crypt() of its own)
- (djm) Avoid a warning in bsd-bindresvport.c
- (djm) Try to avoid adding -I/usr/include to CPPFLAGS during SSL tests. This
- can cause weird segfaults errors on Solaris
+ can cause weird segfaults errors on Solaris
- (djm) Avoid warning in PAM code by making read_passphrase arguments const
- (djm) Add --with-pam to RPM spec files
@@ -345,7 +368,7 @@
[auth.c sshd.8]
support supplementary group in {Allow,Deny}Groups
from stevesk@pobox.com
-
+
20010112
- (bal) OpenBSD Sync
- markus@cvs.openbsd.org 2001/01/10 22:56:22
@@ -358,11 +381,11 @@
use #defines from the draft
move #definations to sftp.h
more info:
- http://www.ietf.org/internet-drafts/draft-ietf-secsh-filexfer-00.txt
+ http://www.ietf.org/internet-drafts/draft-ietf-secsh-filexfer-00.txt
- markus@cvs.openbsd.org 2001/01/10 19:43:20
[sshd.c]
XXX - generate_empheral_server_key() is not safe against races,
- because it calls log()
+ because it calls log()
- markus@cvs.openbsd.org 2001/01/09 21:19:50
[packet.c]
allow TCP_NDELAY for ipv6; from netbsd via itojun@
@@ -446,7 +469,7 @@
[sshconnect2.c]
handle SSH2_MSG_USERAUTH_BANNER; fixes bug when connecting to a server
that prints a banner (e.g. /etc/issue.net)
-
+
20010105
- (bal) contrib/caldera/ provided by Tim Rice <tim@multitalents.net>
- (bal) bsd-getcwd.c and bsd-setenv.c changed from bcopy() to memmove()
@@ -464,9 +487,9 @@
log remote ip on disconnect; PR 1600 from jcs@rt.fm
- markus@cvs.openbsd.org 2001/01/02 20:50:56
[sshconnect.c]
- strict_host_key_checking for host_status != HOST_CHANGED &&
+ strict_host_key_checking for host_status != HOST_CHANGED &&
ip_status == HOST_CHANGED
- - (bal) authfile.c: Synced CVS ID tag
+ - (bal) authfile.c: Synced CVS ID tag
- (bal) UnixWare 2.0 fixes by Tim Rice <tim@multitalents.net>
- (bal) Disable sftp-server if no 64bit int support exists. Based on
patch by Tim Rice <tim@multitalents.net>
@@ -496,11 +519,11 @@
- (bal) if no MAXHOSTNAMELEN is defined. Default to 64 character defination.
Suggested by Christian Kurz <shorty@debian.org>
- (bal) Add in '.c.o' section to Makefile.in to address make programs that
- don't honor CPPFLAGS by default. Suggested by Lutz Jaenicke
+ don't honor CPPFLAGS by default. Suggested by Lutz Jaenicke
<Lutz.Jaenicke@aet.TU-Cottbus.DE>
20001229
- - (bal) Fixed spelling of 'authorized_keys' in ssh-copy-id.1 by Christian
+ - (bal) Fixed spelling of 'authorized_keys' in ssh-copy-id.1 by Christian
Kurz <shorty@debian.org>
- (bal) OpenBSD CVS Update
- markus@cvs.openbsd.org 2000/12/28 14:25:51
@@ -544,21 +567,21 @@
bad reference to 'NeXT including it else were' on the #ifdef version.
20001227
- - (bal) Typo in configure.in: entut?ent should be endut?ent. Suggested by
+ - (bal) Typo in configure.in: entut?ent should be endut?ent. Suggested by
Takumi Yamane <yamtak@b-session.com>
- (bal) Checks for getrlimit(), sysconf(), and setdtablesize(). Patch
by Corinna Vinschen <vinschen@redhat.com>
- (djm) Fix catman-do target for non-bash
- - (bal) Typo in configure.in: entut?ent should be endut?ent. Suggested by
+ - (bal) Typo in configure.in: entut?ent should be endut?ent. Suggested by
Takumi Yamane <yamtak@b-session.com>
- (bal) Checks for getrlimit(), sysconf(), and setdtablesize(). Patch
by Corinna Vinschen <vinschen@redhat.com>
- (djm) Fix catman-do target for non-bash
- - (bal) Fixed NeXT's lack of CPPFLAGS honoring.
- - (bal) ssh-keyscan.c: NeXT (and older BSDs) don't support getrlimit() w/
+ - (bal) Fixed NeXT's lack of CPPFLAGS honoring.
+ - (bal) ssh-keyscan.c: NeXT (and older BSDs) don't support getrlimit() w/
'RLIMIT_NOFILE'
- - (djm) Remove *.Ylonen files. They are no longer in the OpenBSD tree,
- the info in COPYING.Ylonen has been moved to the start of each
+ - (djm) Remove *.Ylonen files. They are no longer in the OpenBSD tree,
+ the info in COPYING.Ylonen has been moved to the start of each
SSH1-derived file and README.Ylonen is well out of date.
20001223
@@ -609,9 +632,9 @@
- markus@cvs.openbsd.org 2000/12/17 02:33:40
[uidswap.c]
typo; from wsanchez@apple.com
-
+
20001220
- - (djm) Workaround PAM inconsistencies between Solaris derived PAM code
+ - (djm) Workaround PAM inconsistencies between Solaris derived PAM code
and Linux-PAM. Based on report and fix from Andrew Morgan
<morgan@transmeta.com>
@@ -672,7 +695,7 @@
- (stevesk) OpenBSD CVS update:
- markus@cvs.openbsd.org 2000/12/12 15:30:02
[ssh-keyscan.c ssh.c sshd.c]
- consistently use __progname; from stevesk@pobox.com
+ consistently use __progname; from stevesk@pobox.com
20001211
- (bal) Applied patch to include ssh-keyscan into Redhat's package, and
@@ -686,16 +709,16 @@
20001210
- (bal) OpenBSD CVS updates
- - markus@cvs.openbsd.org 2000/12/09 13:41:51
+ - markus@cvs.openbsd.org 2000/12/09 13:41:51
[cipher.c cipher.h rijndael.c rijndael.h rijndael_boxes.h]
undo rijndael changes
- - markus@cvs.openbsd.org 2000/12/09 13:48:31
+ - markus@cvs.openbsd.org 2000/12/09 13:48:31
[rijndael.c]
fix byte order bug w/o introducing new implementation
- - markus@cvs.openbsd.org 2000/12/09 14:08:27
+ - markus@cvs.openbsd.org 2000/12/09 14:08:27
[sftp-server.c]
"" -> "." for realpath; from vinschen@redhat.com
- - markus@cvs.openbsd.org 2000/12/09 14:06:54
+ - markus@cvs.openbsd.org 2000/12/09 14:06:54
[ssh-agent.c]
extern int optind; from stevesk@sweden.hp.com
- provos@cvs.openbsd.org 2000/12/09 23:51:11
@@ -704,19 +727,19 @@
20001209
- (bal) OpenBSD CVS updates:
- - djm@cvs.openbsd.org 2000/12/07 4:24:59
+ - djm@cvs.openbsd.org 2000/12/07 4:24:59
[ssh.1]
Typo fix from Wilfredo Sanchez <wsanchez@apple.com>; ok theo
20001207
- (bal) OpenBSD CVS updates:
- - markus@cvs.openbsd.org 2000/12/06 22:58:14
+ - markus@cvs.openbsd.org 2000/12/06 22:58:14
[compat.c compat.h packet.c]
disable debug messages for ssh.com/f-secure 2.0.1x, 2.1.0
- markus@cvs.openbsd.org 2000/12/06 23:10:39
[rijndael.c]
unexpand(1)
- - markus@cvs.openbsd.org 2000/12/06 23:05:43
+ - markus@cvs.openbsd.org 2000/12/06 23:05:43
[cipher.c cipher.h rijndael.c rijndael.h rijndael_boxes.h]
new rijndael implementation. fixes endian bugs
@@ -746,14 +769,14 @@
20001204
- (bal) More C functions defined in NeXT that are unaccessable without
- defining -POSIX.
- - (bal) OpenBSD CVS updates:
- - markus@cvs.openbsd.org 2000/12/03 11:29:04
+ defining -POSIX.
+ - (bal) OpenBSD CVS updates:
+ - markus@cvs.openbsd.org 2000/12/03 11:29:04
[compat.c]
remove fallback to SSH_BUG_HMAC now that the drafts are updated
- markus@cvs.openbsd.org 2000/12/03 11:27:55
[compat.c]
- correctly match "2.1.0.pl2 SSH" etc; from
+ correctly match "2.1.0.pl2 SSH" etc; from
pekkas@netcore.fi/bugzilla.redhat
- markus@cvs.openbsd.org 2000/12/03 11:15:03
[auth2.c compat.c compat.h sshconnect2.c]
@@ -763,7 +786,7 @@
- (bal) OpenBSD CVS updates:
- markus@cvs.openbsd.org 2000/11/30 22:54:31
[channels.c]
- debug->warn if tried to do -R style fwd w/o client requesting this;
+ debug->warn if tried to do -R style fwd w/o client requesting this;
ok neils@
- markus@cvs.openbsd.org 2000/11/29 20:39:17
[cipher.c]
@@ -771,7 +794,7 @@
- markus@cvs.openbsd.org 2000/11/30 18:33:05
[ssh-agent.c]
agents must not dump core, ok niels@
- - markus@cvs.openbsd.org 2000/11/30 07:04:02
+ - markus@cvs.openbsd.org 2000/11/30 07:04:02
[ssh.1]
T is for both protocols
- markus@cvs.openbsd.org 2000/12/01 00:00:51
@@ -782,7 +805,7 @@
check -T before isatty()
- provos@cvs.openbsd.org 2000/11/29 13:51:27
[sshconnect.c]
- show IP address and hostname when new key is encountered. okay markus@
+ show IP address and hostname when new key is encountered. okay markus@
- markus@cvs.openbsd.org 2000/11/30 22:53:35
[sshconnect.c]
disable agent/x11/port fwding if hostkey has changed; ok niels@
@@ -796,14 +819,14 @@
20001202
- (bal) Backed out of part of Alain St-Denis' loginrec.c patch.
- - (bal) Irix need some sort of mansubdir, patch by Michael Stone
+ - (bal) Irix need some sort of mansubdir, patch by Michael Stone
<mstone@cs.loyola.edu>
20001129
- (djm) Back out all the serverloop.c hacks. sshd will now hang again
if there are background children with open fds.
- (djm) bsd-rresvport.c bzero -> memset
- - (djm) Don't fail in defines.h on absence of 64 bit types (we will
+ - (djm) Don't fail in defines.h on absence of 64 bit types (we will
still fail during compilation of sftp-server).
- (djm) Fail if ar is not found during configure
- (djm) OpenBSD CVS updates:
@@ -833,7 +856,7 @@
- (bal) Merge OpenBSD changes:
- markus@cvs.openbsd.org 2000/11/15 22:31:36
[auth-options.c]
- case insensitive key options; from stevesk@sweeden.hp.com
+ case insensitive key options; from stevesk@sweeden.hp.com
- markus@cvs.openbsd.org 2000/11/16 17:55:43
[dh.c]
do not use perror() in sshd, after child is forked()
@@ -851,7 +874,7 @@
do not reorder keys if a key is removed
- markus@cvs.openbsd.org 2000/11/15 19:58:08
[ssh.c]
- just ignore non existing user keys
+ just ignore non existing user keys
- millert@cvs.openbsd.org 200/11/15 20:24:43
[ssh-keygen.c]
Add missing \n at end of error message.
@@ -864,7 +887,7 @@
20001117
- (bal) Changed from 'primes' to 'primes.out' for consistancy sake. It
has no affect the output. Patch by Corinna Vinschen <vinschen@redhat.com>
- - (stevesk) Reworked progname support.
+ - (stevesk) Reworked progname support.
- (bal) Misplaced #include "includes.h" in bsd-setproctitle.c. Patch by
Shinichi Maruyama <marya@st.jip.co.jp>
@@ -875,7 +898,7 @@
<roth@feep.net>
20001113
- - (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to
+ - (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to
contrib/README
- (djm) Merge OpenBSD changes:
- markus@cvs.openbsd.org 2000/11/06 16:04:56
@@ -902,7 +925,7 @@
[readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c]
[ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config]
[sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c]
- [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h]
+ [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h]
add support for RSA to SSH2. please test.
there are now 3 types of keys: RSA1 is used by ssh-1 only,
RSA and DSA are used by SSH2.
@@ -926,10 +949,10 @@
- (djm) Added /etc/primes for kex DH group neg, fixup Makefile.in and
packaging files
- (djm) Fix new Makefile.in warnings
- - (djm) Fix vsprintf("%h") in bsd-snprintf.c, short int va_args are
- promoted to type int. Report and fix from Dan Astoorian
+ - (djm) Fix vsprintf("%h") in bsd-snprintf.c, short int va_args are
+ promoted to type int. Report and fix from Dan Astoorian
<djast@cs.toronto.edu>
- - (djm) Hardwire sysconfdir in RPM spec files as some RPM versions get
+ - (djm) Hardwire sysconfdir in RPM spec files as some RPM versions get
it wrong. Report from Bennett Todd <bet@rahul.net>
20001110
@@ -937,10 +960,10 @@
- (bal) Changed from --with-skey to --with-skey=PATH in configure.in
- (bal) Added in check to verify S/Key library is being detected in
configure.in
- - (bal) next-posix.h - added another prototype wrapped in POSIX ifdef/endif.
+ - (bal) next-posix.h - added another prototype wrapped in POSIX ifdef/endif.
Patch by Mark Miller <markm@swoon.net>
- (bal) Added 'util.h' header to loginrec.c only if HAVE_UTIL_H is defined
- to remove warnings under MacOS X. Patch by Mark Miller <markm@swoon.net>
+ to remove warnings under MacOS X. Patch by Mark Miller <markm@swoon.net>
- (bal) Fixed LDFLAG mispelling in configure.in for --with-afs
20001107
@@ -954,7 +977,7 @@
20001106
- (djm) Use Jim's new 1.0.3 askpass in Redhat RPMs
- (djm) Manually fix up missed diff hunks (mainly RCS idents)
- - (djm) Remove UPGRADING document in favour of a link to the better
+ - (djm) Remove UPGRADING document in favour of a link to the better
maintained FAQ on www.openssh.com
- (djm) Fix multiple dependancy on gnome-libs from Pekka Savola
<pekkas@netcore.fi>
@@ -989,10 +1012,10 @@
- (bal) next-posix.h - spelling and forgot a prototype
20001028
- - (djm) fix select hack in serverloop.c from Philippe WILLEM
+ - (djm) fix select hack in serverloop.c from Philippe WILLEM
<Philippe.WILLEM@urssaf.fr>
- (djm) Fix mangled AIXAUTHENTICATE code
- - (djm) authctxt->pw may be NULL. Fix from Markus Friedl
+ - (djm) authctxt->pw may be NULL. Fix from Markus Friedl
<markus.friedl@informatik.uni-erlangen.de>
- (djm) Sync with OpenBSD:
- markus@cvs.openbsd.org 2000/10/16 15:46:32
@@ -1029,7 +1052,7 @@
- markus@cvs.openbsd.org 2000/10/27 01:32:19
[channels.c channels.h clientloop.c serverloop.c session.c]
[ssh.c util.c]
- enable non-blocking IO on channels, and tty's (except for the
+ enable non-blocking IO on channels, and tty's (except for the
client ttys).
20001027
@@ -1060,7 +1083,7 @@
supplied passphrase. Problem report from Lutz Jaenicke
<Lutz.Jaenicke@aet.TU-Cottbus.DE>
- (bal) Changed from GNU rx to PCRE on suggestion from djm.
- - (bal) Integrated Sony NEWS-OS patches from NAKAJI Hirouyuki
+ - (bal) Integrated Sony NEWS-OS patches from NAKAJI Hirouyuki
<nakaji@tutrp.tut.ac.jp>
20001016
@@ -1079,7 +1102,7 @@
AllowTcpForwarding; from naddy@
- markus@cvs.openbsd.org 2000/10/14 06:16:56
[auth2.c compat.c compat.h sshconnect2.c version.h]
- OpenSSH_2.3; note that is is not complete, but the version number
+ OpenSSH_2.3; note that is is not complete, but the version number
needs to be changed for interoperability reasons
- markus@cvs.openbsd.org 2000/10/14 06:19:45
[auth-rsa.c]
@@ -1091,12 +1114,12 @@
- markus@cvs.openbsd.org 2000/10/15 08:18:31
[rijndael.c]
typo
- - (djm) Copy manpages back over from OpenBSD - too tedious to wade
+ - (djm) Copy manpages back over from OpenBSD - too tedious to wade
through diffs
- - (djm) Added condrestart to Redhat init script. Patch from Pekka Savola
+ - (djm) Added condrestart to Redhat init script. Patch from Pekka Savola
<pekkas@netcore.fi>
- (djm) Update version in Redhat spec file
- - (djm) Merge some of Nalin Dahyabhai <nalin@redhat.com> changes from the
+ - (djm) Merge some of Nalin Dahyabhai <nalin@redhat.com> changes from the
Redhat 7.0 spec file
- (djm) Make inability to read/write PRNG seedfile non-fatal
@@ -1108,7 +1131,7 @@
- (bal) Add support for realpath and getcwd for platforms with broken
or missing realpath implementations for sftp-server.
- (bal) Corrected mistake in INSTALL in regards to GNU rx library
- - (bal) Add support for GNU rx library for those lacking regexp support
+ - (bal) Add support for GNU rx library for those lacking regexp support
- (djm) Don't accept PAM_PROMPT_ECHO_ON messages during initial auth
- (djm) Revert SSH2 serverloop hack, will find a better way.
- (djm) Add workaround for Linux 2.4's gratuitious errno change. Patch
@@ -1214,11 +1237,11 @@
20000930
- (djm) Irix ssh_prng_cmds path fix from Pekka Savola <pekkas@netcore.fi>
- - (djm) Support in bsd-snprintf.c for long long conversions from
+ - (djm) Support in bsd-snprintf.c for long long conversions from
Ben Lindstrom <mouring@pconline.com>
- (djm) Cleanup NeXT support from Ben Lindstrom <mouring@pconline.com>
- (djm) Ignore SIGPIPEs from serverloop to child. Fixes crashes with
- very short lived X connections. Bug report from Tobias Oetiker
+ very short lived X connections. Bug report from Tobias Oetiker
<oetiker@ee.ethz.ch>. Fix from Markus Friedl <markus@cvs.openbsd.org>
- (djm) Add recent InitScripts as a RPM dependancy for openssh-server
patch from Pekka Savola <pekkas@netcore.fi>
@@ -1234,27 +1257,27 @@
- markus@cvs.openbsd.org 2000/09/28 12:03:18
[channels.c]
debug -> debug2 cleanup
- - (djm) Irix strips "/dev/tty" from [uw]tmp entries (other systems only
+ - (djm) Irix strips "/dev/tty" from [uw]tmp entries (other systems only
strip "/dev/"). Fix loginrec.c based on patch from Alain St-Denis
<Alain.St-Denis@ec.gc.ca>
- - (djm) Fix 9 character passphrase failure with gnome-ssh-askpass.
- Problem was caused by interrupted read in ssh-add. Report from Donald
+ - (djm) Fix 9 character passphrase failure with gnome-ssh-askpass.
+ Problem was caused by interrupted read in ssh-add. Report from Donald
J. Barry <don@astro.cornell.edu>
20000929
- (djm) Fix SSH2 not terminating until all background tasks done problem.
- - (djm) Another off-by-one fix from Pavel Kankovsky
- <peak@argo.troja.mff.cuni.cz>
+ - (djm) Another off-by-one fix from Pavel Kankovsky
+ <peak@argo.troja.mff.cuni.cz>
- (djm) Clean up. Strip some unnecessary differences with OpenBSD's code,
tidy necessary differences. Use Markus' new debugN() in entropy.c
- - (djm) Merged big SCO portability patch from Tim Rice
+ - (djm) Merged big SCO portability patch from Tim Rice
<tim@multitalents.net>
20000926
- (djm) Update X11-askpass to 1.0.2 in RPM spec file
- (djm) Define _REENTRANT to pickup strtok_r() on HP/UX
- - (djm) Security: fix off-by-one buffer overrun in fake-getnameinfo.c.
- Report and fix from Pavel Kankovsky <peak@argo.troja.mff.cuni.cz>
+ - (djm) Security: fix off-by-one buffer overrun in fake-getnameinfo.c.
+ Report and fix from Pavel Kankovsky <peak@argo.troja.mff.cuni.cz>
20000924
- (djm) Merged cleanup patch from Mark Miller <markm@swoon.net>
@@ -1263,14 +1286,14 @@
<markm@swoon.net>
20000923
- - (djm) Fix address logging in utmp from Kevin Steves
+ - (djm) Fix address logging in utmp from Kevin Steves
<stevesk@sweden.hp.com>
- (djm) Redhat spec and manpage fixes from Pekka Savola <pekkas@netcore.fi>
- (djm) Seperate tests for int64_t and u_int64_t types
- - (djm) Tweak password expiry checking at suggestion of Kevin Steves
+ - (djm) Tweak password expiry checking at suggestion of Kevin Steves
<stevesk@sweden.hp.com>
- (djm) NeXT patch from Ben Lindstrom <mouring@pconline.com>
- - (djm) Use printf %lld instead of %qd in sftp-server.c. Fix from
+ - (djm) Use printf %lld instead of %qd in sftp-server.c. Fix from
Michael Stone <mstone@cs.loyola.edu>
- (djm) OpenBSD CVS sync:
- markus@cvs.openbsd.org 2000/09/17 09:38:59
@@ -1304,13 +1327,13 @@
<asminer@cs.iastate.edu>
20000916
- - (djm) Fix SSL search order from Lutz Jaenicke
+ - (djm) Fix SSL search order from Lutz Jaenicke
<Lutz.Jaenicke@aet.TU-Cottbus.DE>
- (djm) New SuSE spec from Corinna Vinschen <corinna@vinschen.de>
- (djm) Update CygWin support from Corinna Vinschen <vinschen@cygnus.com>
- (djm) Use a real struct sockaddr inside the fake struct sockaddr_storage.
Patch from Larry Jones <larry.jones@sdrc.com>
- - (djm) Add Steve VanDevender's <stevev@darkwing.uoregon.edu> PAM
+ - (djm) Add Steve VanDevender's <stevev@darkwing.uoregon.edu> PAM
password change patch.
- (djm) Bring licenses on my stuff in line with OpenBSD's
- (djm) Cleanup auth-passwd.c and unify HP/UX authentication. Patch from
@@ -1321,9 +1344,9 @@
- (djm) Update Redhat SPEC file accordingly
- (djm) Add Kevin Steves <stevesk@sweden.hp.com> HP/UX contrib files
- (djm) Add Charles Levert <charles@comm.polymtl.ca> getpgrp patch
- - (djm) Fix password auth on HP/UX 10.20. Patch from Dirk De Wachter
+ - (djm) Fix password auth on HP/UX 10.20. Patch from Dirk De Wachter
<Dirk.DeWachter@rug.ac.be>
- - (djm) Fixprogs and entropy list fixes from Larry Jones
+ - (djm) Fixprogs and entropy list fixes from Larry Jones
<larry.jones@sdrc.com>
- (djm) Fix for SuSE spec file from Takashi YOSHIDA
<tyoshida@gemini.rc.kyushu-u.ac.jp>
@@ -1342,10 +1365,10 @@
prototype
- deraadt@cvs.openbsd.org 2000/09/07 14:27:56
[ALL]
- cleanup copyright notices on all files. I have attempted to be
- accurate with the details. everything is now under Tatu's licence
- (which I copied from his readme), and/or the core-sdi bsd-ish thing
- for deattack, or various openbsd developers under a 2-term bsd
+ cleanup copyright notices on all files. I have attempted to be
+ accurate with the details. everything is now under Tatu's licence
+ (which I copied from his readme), and/or the core-sdi bsd-ish thing
+ for deattack, or various openbsd developers under a 2-term bsd
licence. We're not changing any rules, just being accurate.
- markus@cvs.openbsd.org 2000/09/07 14:40:30
[channels.c channels.h clientloop.c serverloop.c ssh.c]
@@ -1799,7 +1822,7 @@
- (djm) Added 'distprep' make target to simplify packaging
- (djm) Added patch from Chris Adams <cmadams@hiwaay.net> to add OSF SIA
support. Enable using "USE_SIA=1 ./configure [options]"
-
+
20000627
- (djm) Fixes to login code - not setting li->uid, cleanups
- (djm) Formatting
@@ -1921,7 +1944,7 @@
- Don't try to retrieve lastlog from wtmp/wtmpx if DISABLE_LASTLOG is
def'd
- Set AIX to use preformatted manpages
-
+
20000610
- (djm) Minor doc tweaks
- (djm) Fix for configure on bash2 from Jim Knoble <jmknoble@jmknoble.cx>
@@ -1947,7 +1970,7 @@
teach protocol v2 to count login failures properly and also enable an
explanation of why the password prompt comes up again like v1; this is NOT
crypto
- - markus@cvs.openbsd.org
+ - markus@cvs.openbsd.org
[readconf.c readconf.h servconf.c servconf.h session.c ssh.1 ssh.c sshd.8]
xauth_location support; pr 1234
[readconf.c sshconnect2.c]
@@ -1978,7 +2001,7 @@
- (andre) New login code
- Remove bsd-login.[ch] and all the OpenBSD-derived code in login.c
- Add loginrec.[ch], logintest.c and autoconf code
-
+
20000531
- Cleanup of auth.c, login.c and fake-*
- Cleanup of auth-pam.c, save and print "account expired" error messages
@@ -2383,7 +2406,7 @@
no adjust after close
- [sshd.c compat.c ]
interop w/ latest ssh.com windows client.
-
+
20000406
- OpenBSD CVS update:
- [channels.c]
@@ -2704,7 +2727,7 @@
- [readpass.c]
instead of blocking SIGINT, catch it ourselves, so that we can clean
the tty modes up and kill ourselves -- instead of our process group
- leader (scp, cvs, ...) going away and leaving us in noecho mode.
+ leader (scp, cvs, ...) going away and leaving us in noecho mode.
people with cbreak shells never even noticed..
- [ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8]
ie. -> i.e.,
@@ -2741,7 +2764,7 @@
20000118
- Fixed --with-pid-dir option
- Makefile fix from Gary E. Miller <gem@rellim.com>
- - Compile fix for HPUX and Solaris from Andre Lucas
+ - Compile fix for HPUX and Solaris from Andre Lucas
<andre.lucas@dial.pipex.com>
20000117
@@ -2844,7 +2867,7 @@
20000103
- Add explicit make rules for files proccessed by fixpaths.
- - Fix "make install" in RPM spec files. Report from Tenkou N. Hattori
+ - Fix "make install" in RPM spec files. Report from Tenkou N. Hattori
<tnh@kondara.org>
- Removed "nullok" directive from default PAM configuration files.
Added information on enabling EmptyPasswords on openssh+PAM in
@@ -3019,7 +3042,7 @@
- Use LDFLAGS correctly
- Fix SIGIO error in scp
- Simplify status line printing in scp
- - Added better test for inline functions compiler support from
+ - Added better test for inline functions compiler support from
Darren_Hall@progressive.com
19991214
@@ -3247,7 +3270,7 @@
print usage() everytime we get bad options
- [ssh-keygen.c] overflow, djm@mindrot.org
- [sshd.c] fix sigchld race; cjc5@po.cwru.edu
-
+
19991120
- Merged more Solaris support from Marc G. Fournier
<marc.fournier@acadiau.ca>
diff --git a/Makefile.in b/Makefile.in
index c3cd580e..8ea71915 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -33,9 +33,9 @@ SSH_MODE= @SSHMODE@
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
-@NO_SFTP@SFTP-SERVER=sftp-server$(EXEEXT)
+@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-SERVER)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) $(SFTP_PROGS)
LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o cli.o compat.o compress.o crc32.o deattack.o dispatch.o hmac.o hostfile.o key.o kex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o
@@ -43,8 +43,8 @@ SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o
SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o dh.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o
-TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8
-CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh-keyscan.0 ssh.0 sshd.0 sftp-server.0
+TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1
+CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh-keyscan.0 ssh.0 sshd.0 sftp-server.0 sftp.1
MANPAGES = @MANTYPE@
CONFIGFILES=sshd_config ssh_config primes
@@ -105,8 +105,12 @@ ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o log-client.o
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a log-client.o ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o log-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
-sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp-server.o log-server.o
- $(LD) -o $@ sftp-server.o log-server.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp-server.o sftp-common.o log-server.o
+ $(LD) -o $@ sftp-server.o sftp-common.o log-server.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+# XXX: need to -lssh twice here!
+sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o log-client.o
+ $(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o log-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
# test driver for the loginrec code - not built by default
logintest: logintest.o $(LIBCOMPAT) libssh.a log-client.o loginrec.o
@@ -156,6 +160,7 @@ install-files:
$(INSTALL) -m 0755 -s ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen
$(INSTALL) -m 0775 -s ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan
$(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd
+ @NO_SFTP@$$(INSTALL) -m 0755 -s sftp $(DESTDIR)$(bindir)/sftp
@NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(libexecdir)/sftp-server
$(INSTALL) -m 644 ssh.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
$(INSTALL) -m 644 scp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
@@ -164,6 +169,7 @@ install-files:
$(INSTALL) -m 644 ssh-keygen.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
$(INSTALL) -m 644 ssh-keyscan.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
$(INSTALL) -m 644 sshd.[08].out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+ @NO_SFTP@$$(INSTALL) -m 644 sftp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
@NO_SFTP@$(INSTALL) -m 644 sftp-server.[08].out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
-rm -f $(DESTDIR)$(bindir)/slogin
ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
@@ -241,6 +247,7 @@ uninstall:
-rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+ -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
-rm -r $(DESTDIR)$(libexecdir)/sftp-server$(EXEEXT)
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
@@ -248,6 +255,7 @@ uninstall:
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
diff --git a/TODO b/TODO
index 62c51e15..1165a0d9 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,6 @@
Programming:
+- Grep for 'XXX' comments and fix
+
- Replacement for setproctitle() - HP/UX support only currently
- Improve PAM support (a pam_lastlog module will cause sshd to exit)
diff --git a/auth-options.c b/auth-options.c
index 5457d9b1..04d2f085 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-options.c,v 1.11 2001/01/21 19:05:41 markus Exp $");
+RCSID("$OpenBSD: auth-options.c,v 1.12 2001/02/03 10:08:36 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -18,6 +18,7 @@ RCSID("$OpenBSD: auth-options.c,v 1.11 2001/01/21 19:05:41 markus Exp $");
#include "log.h"
#include "canohost.h"
#include "auth-options.h"
+#include "servconf.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
@@ -31,6 +32,8 @@ char *forced_command = NULL;
/* "environment=" options. */
struct envstring *custom_environment = NULL;
+extern ServerOptions options;
+
void
auth_clear_options(void)
{
@@ -55,61 +58,61 @@ auth_clear_options(void)
* side effect: sets key option flags
*/
int
-auth_parse_options(struct passwd *pw, char *options, char *file, u_long linenum)
+auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
{
const char *cp;
- if (!options)
+ if (!opts)
return 1;
/* reset options */
auth_clear_options();
- while (*options && *options != ' ' && *options != '\t') {
+ while (*opts && *opts != ' ' && *opts != '\t') {
cp = "no-port-forwarding";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("Port forwarding disabled.");
no_port_forwarding_flag = 1;
- options += strlen(cp);
+ opts += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
- options += strlen(cp);
+ opts += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
- options += strlen(cp);
+ opts += strlen(cp);
goto next_option;
}
cp = "no-pty";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
packet_send_debug("Pty allocation disabled.");
no_pty_flag = 1;
- options += strlen(cp);
+ opts += strlen(cp);
goto next_option;
}
cp = "command=\"";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
int i;
- options += strlen(cp);
- forced_command = xmalloc(strlen(options) + 1);
+ opts += strlen(cp);
+ forced_command = xmalloc(strlen(opts) + 1);
i = 0;
- while (*options) {
- if (*options == '"')
+ while (*opts) {
+ if (*opts == '"')
break;
- if (*options == '\\' && options[1] == '"') {
- options += 2;
+ if (*opts == '\\' && opts[1] == '"') {
+ opts += 2;
forced_command[i++] = '"';
continue;
}
- forced_command[i++] = *options++;
+ forced_command[i++] = *opts++;
}
- if (!*options) {
+ if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
@@ -118,28 +121,28 @@ auth_parse_options(struct passwd *pw, char *options, char *file, u_long linenum)
}
forced_command[i] = 0;
packet_send_debug("Forced command: %.900s", forced_command);
- options++;
+ opts++;
goto next_option;
}
cp = "environment=\"";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
int i;
char *s;
struct envstring *new_envstring;
- options += strlen(cp);
- s = xmalloc(strlen(options) + 1);
+ opts += strlen(cp);
+ s = xmalloc(strlen(opts) + 1);
i = 0;
- while (*options) {
- if (*options == '"')
+ while (*opts) {
+ if (*opts == '"')
break;
- if (*options == '\\' && options[1] == '"') {
- options += 2;
+ if (*opts == '\\' && opts[1] == '"') {
+ opts += 2;
s[i++] = '"';
continue;
}
- s[i++] = *options++;
+ s[i++] = *opts++;
}
- if (!*options) {
+ if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
@@ -149,7 +152,7 @@ auth_parse_options(struct passwd *pw, char *options, char *file, u_long linenum)
s[i] = 0;
packet_send_debug("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
- options++;
+ opts++;
new_envstring = xmalloc(sizeof(struct envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
@@ -157,23 +160,26 @@ auth_parse_options(struct passwd *pw, char *options, char *file, u_long linenum)
goto next_option;
}
cp = "from=\"";
- if (strncasecmp(options, cp, strlen(cp)) == 0) {
+ if (strncasecmp(opts, cp, strlen(cp)) == 0) {
int mname, mip;
- char *patterns = xmalloc(strlen(options) + 1);
+ const char *remote_ip = get_remote_ipaddr();
+ const char *remote_host = get_canonical_hostname(
+ options.reverse_mapping_check);
+ char *patterns = xmalloc(strlen(opts) + 1);
int i;
- options += strlen(cp);
+ opts += strlen(cp);
i = 0;
- while (*options) {
- if (*options == '"')
+ while (*opts) {
+ if (*opts == '"')
break;
- if (*options == '\\' && options[1] == '"') {
- options += 2;
+ if (*opts == '\\' && opts[1] == '"') {
+ opts += 2;
patterns[i++] = '"';
continue;
}
- patterns[i++] = *options++;
+ patterns[i++] = *opts++;
}
- if (!*options) {
+ if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
@@ -181,24 +187,26 @@ auth_parse_options(struct passwd *pw, char *options, char *file, u_long linenum)
continue;
}
patterns[i] = 0;
- options++;
+ opts++;
/*
* Deny access if we get a negative
* match for the hostname or the ip
* or if we get not match at all
*/
- mname = match_hostname(get_canonical_hostname(),
- patterns, strlen(patterns));
- mip = match_hostname(get_remote_ipaddr(),
- patterns, strlen(patterns));
+ mname = match_hostname(remote_host, patterns,
+ strlen(patterns));
+ mip = match_hostname(remote_ip, patterns,
+ strlen(patterns));
xfree(patterns);
if (mname == -1 || mip == -1 ||
(mname != 1 && mip != 1)) {
- log("Authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
- pw->pw_name, get_canonical_hostname(),
- get_remote_ipaddr());
- packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
- get_canonical_hostname());
+ log("Authentication tried for %.100s with "
+ "correct key but not from a permitted "
+ "host (host=%.200s, ip=%.200s).",
+ pw->pw_name, remote_host, remote_ip);
+ packet_send_debug("Your host '%.200s' is not "
+ "permitted to use this key for login.",
+ remote_host);
/* deny access */
return 0;
}
@@ -210,13 +218,13 @@ next_option:
* Skip the comma, and move to the next option
* (or break out if there are no more).
*/
- if (!*options)
+ if (!*opts)
fatal("Bugs in auth-options.c option processing.");
- if (*options == ' ' || *options == '\t')
+ if (*opts == ' ' || *opts == '\t')
break; /* End of options. */
- if (*options != ',')
+ if (*opts != ',')
goto bad_option;
- options++;
+ opts++;
/* Process the next option. */
}
/* grant access */
@@ -224,9 +232,9 @@ next_option:
bad_option:
log("Bad options in %.100s file, line %lu: %.50s",
- file, linenum, options);
+ file, linenum, opts);
packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
- file, linenum, options);
+ file, linenum, opts);
/* deny access */
return 0;
}
diff --git a/auth-pam.c b/auth-pam.c
index 3d550b4d..122896c7 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -32,7 +32,7 @@
#include "canohost.h"
#include "readpass.h"
-RCSID("$Id: auth-pam.c,v 1.22 2001/01/22 05:34:40 mouring Exp $");
+RCSID("$Id: auth-pam.c,v 1.23 2001/02/04 12:20:19 djm Exp $");
#define NEW_AUTHTOK_MSG \
"Warning: Your password has expired, please change it now"
@@ -211,10 +211,12 @@ int auth_pam_password(struct passwd *pw, const char *password)
int do_pam_account(char *username, char *remote_user)
{
int pam_retval;
+ extern ServerOptions options;
- debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
+ debug("PAM setting rhost to \"%.200s\"",
+ get_canonical_hostname(options.reverse_mapping_check));
pam_retval = pam_set_item(pamh, PAM_RHOST,
- get_canonical_hostname());
+ get_canonical_hostname(options.reverse_mapping_check));
if (pam_retval != PAM_SUCCESS) {
fatal("PAM set rhost failed[%d]: %.200s",
pam_retval, PAM_STRERROR(pamh, pam_retval));
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
index 87d51549..0edbdb5f 100644
--- a/auth-rh-rsa.c
+++ b/auth-rh-rsa.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rh-rsa.c,v 1.21 2001/01/21 19:05:42 markus Exp $");
+RCSID("$OpenBSD: auth-rh-rsa.c,v 1.22 2001/02/03 10:08:36 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -49,7 +49,8 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
if (!auth_rhosts(pw, client_user))
return 0;
- canonical_hostname = get_canonical_hostname();
+ canonical_hostname = get_canonical_hostname(
+ options.reverse_mapping_check);
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
diff --git a/auth-rhosts.c b/auth-rhosts.c
index 4f9ea886..d8d10ffc 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -14,7 +14,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rhosts.c,v 1.19 2001/01/21 19:05:42 markus Exp $");
+RCSID("$OpenBSD: auth-rhosts.c,v 1.20 2001/02/03 10:08:36 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -183,7 +183,7 @@ auth_rhosts(struct passwd *pw, const char *client_user)
stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
return 0;
- hostname = get_canonical_hostname();
+ hostname = get_canonical_hostname(options.reverse_mapping_check);
ipaddr = get_remote_ipaddr();
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
diff --git a/auth.c b/auth.c
index 187216d2..4e3cf675 100644
--- a/auth.c
+++ b/auth.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.14 2001/01/21 19:05:43 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.15 2001/02/03 10:08:37 markus Exp $");
#ifdef HAVE_LOGIN_H
#include <login.h>
@@ -228,7 +228,7 @@ auth_root_allowed(void)
log("Root login accepted for forced command.");
return 1;
} else {
- log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
+ log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
return 0;
}
}
diff --git a/auth1.c b/auth1.c
index 6e9808e5..1986b2d8 100644
--- a/auth1.c
+++ b/auth1.c
@@ -266,8 +266,8 @@ do_authloop(Authctxt *authctxt)
#elif defined(HAVE_OSF_SIA)
/* Do SIA auth with password */
if (sia_validate_user(NULL, saved_argc, saved_argv,
- get_canonical_hostname(), pw->pw_name, NULL, 0,
- NULL, password) == SIASUCCESS) {
+ get_canonical_hostname(options.reverse_mapping_check),
+ pw->pw_name, NULL, 0, NULL, password) == SIASUCCESS) {
authenticated = 1;
}
#else /* !USE_PAM && !HAVE_OSF_SIA */
@@ -347,7 +347,9 @@ do_authloop(Authctxt *authctxt)
if (authctxt->failures++ > AUTH_FAIL_MAX) {
#ifdef WITH_AIXAUTHENTICATE
- loginfailed(user,get_canonical_hostname(),"ssh");
+ loginfailed(user,
+ get_canonical_hostname(options.reverse_mapping_check),
+ "ssh");
#endif /* WITH_AIXAUTHENTICATE */
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
}
@@ -433,7 +435,9 @@ do_authentication()
#ifdef WITH_AIXAUTHENTICATE
/* We don't have a pty yet, so just label the line as "ssh" */
- if (loginsuccess(authctxt->user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
+ if (loginsuccess(authctxt->user,
+ get_canonical_hostname(options.reverse_mapping_check),
+ "ssh", &aixloginmsg) < 0)
aixloginmsg = NULL;
#endif /* WITH_AIXAUTHENTICATE */
diff --git a/auth2.c b/auth2.c
index cff34c60..5f8b4234 100644
--- a/auth2.c
+++ b/auth2.c
@@ -310,7 +310,8 @@ userauth_reply(Authctxt *authctxt, int authenticated)
#ifdef WITH_AIXAUTHENTICATE
/* We don't have a pty yet, so just label the line as "ssh" */
if (loginsuccess(authctxt->user?authctxt->user:"NOUSER",
- get_canonical_hostname(), "ssh", &aixloginmsg) < 0)
+ get_canonical_hostname(options.reverse_mapping_check),
+ "ssh", &aixloginmsg) < 0)
aixloginmsg = NULL;
#endif /* WITH_AIXAUTHENTICATE */
/* turn off userauth */
@@ -354,8 +355,9 @@ userauth_none(Authctxt *authctxt)
return auth_pam_password(authctxt->pw, "");
#elif defined(HAVE_OSF_SIA)
return (sia_validate_user(NULL, saved_argc, saved_argv,
- get_canonical_hostname(), authctxt->user?authctxt->user:"NOUSER",
- NULL, 0, NULL, "") == SIASUCCESS);
+ get_canonical_hostname(options.reverse_mapping_check),
+ authctxt->user?authctxt->user:"NOUSER", NULL, 0,
+ NULL, "") == SIASUCCESS);
#else /* !HAVE_OSF_SIA && !USE_PAM */
return auth_password(authctxt->pw, "");
#endif /* USE_PAM */
@@ -381,8 +383,9 @@ userauth_passwd(Authctxt *authctxt)
auth_pam_password(authctxt->pw, password) == 1)
#elif defined(HAVE_OSF_SIA)
sia_validate_user(NULL, saved_argc, saved_argv,
- get_canonical_hostname(), authctxt->user?authctxt->user:"NOUSER",
- NULL, 0, NULL, password) == SIASUCCESS)
+ get_canonical_hostname(options.reverse_mapping_check),
+ authctxt->user?authctxt->user:"NOUSER", NULL, 0, NULL,
+ password) == SIASUCCESS)
#else /* !USE_PAM && !HAVE_OSF_SIA */
auth_password(authctxt->pw, password) == 1)
#endif /* USE_PAM */
diff --git a/canohost.c b/canohost.c
index f3a65932..8253e9b6 100644
--- a/canohost.c
+++ b/canohost.c
@@ -12,35 +12,35 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: canohost.c,v 1.19 2001/01/29 19:42:33 markus Exp $");
+RCSID("$OpenBSD: canohost.c,v 1.20 2001/02/03 10:08:37 markus Exp $");
#include "packet.h"
#include "xmalloc.h"
#include "log.h"
+void check_ip_options(int socket, char *ipaddr);
+
/*
* Return the canonical name of the host at the other end of the socket. The
* caller should free the returned string with xfree.
*/
char *
-get_remote_hostname(int socket)
+get_remote_hostname(int socket, int reverse_mapping_check)
{
struct sockaddr_storage from;
int i;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
- char name[MAXHOSTNAMELEN];
- char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
+ char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
- if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
+ if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
-
#ifdef IPV4_IN_IPV6
if (from.ss_family == AF_INET6) {
struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from;
@@ -63,6 +63,8 @@ get_remote_hostname(int socket)
}
}
#endif
+ if (from.ss_family == AF_INET)
+ check_ip_options(socket, ntop);
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
@@ -70,120 +72,127 @@ get_remote_hostname(int socket)
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
- NULL, 0, NI_NAMEREQD) == 0) {
- /* Got host name. */
- name[sizeof(name) - 1] = '\0';
- /*
- * Convert it to all lowercase (which is expected by the rest
- * of this software).
- */
- for (i = 0; name[i]; i++)
- if (isupper(name[i]))
- name[i] = tolower(name[i]);
-
- /*
- * Map it back to an IP address and check that the given
- * address actually is an address of this host. This is
- * necessary because anyone with access to a name server can
- * define arbitrary names for an IP address. Mapping from
- * name to IP address can be trusted better (but can still be
- * fooled if the intruder has access to the name server of
- * the domain).
- */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = from.ss_family;
- hints.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
- log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
- strlcpy(name, ntop, sizeof name);
- goto check_ip_options;
- }
- /* Look for the address from the list of addresses. */
- for (ai = aitop; ai; ai = ai->ai_next) {
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
- (strcmp(ntop, ntop2) == 0))
- break;
- }
- freeaddrinfo(aitop);
- /* If we reached the end of the list, the address was not there. */
- if (!ai) {
- /* Address not found for the host name. */
- log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
- ntop, name);
- strlcpy(name, ntop, sizeof name);
- goto check_ip_options;
- }
- /* Address was found for the host name. We accept the host name. */
- } else {
- /* Host name not found. Use ascii representation of the address. */
- strlcpy(name, ntop, sizeof name);
- log("Could not reverse map address %.100s.", name);
+ NULL, 0, NI_NAMEREQD) != 0) {
+ /* Host name not found. Use ip address. */
+ log("Could not reverse map address %.100s.", ntop);
+ return xstrdup(ntop);
}
-check_ip_options:
+ /* Got host name. */
+ name[sizeof(name) - 1] = '\0';
+ /*
+ * Convert it to all lowercase (which is expected by the rest
+ * of this software).
+ */
+ for (i = 0; name[i]; i++)
+ if (isupper(name[i]))
+ name[i] = tolower(name[i]);
+ if (!reverse_mapping_check)
+ return xstrdup(name);
/*
- * If IP options are supported, make sure there are none (log and
- * disconnect them if any are found). Basically we are worried about
- * source routing; it can be used to pretend you are somebody
- * (ip-address) you are not. That itself may be "almost acceptable"
- * under certain circumstances, but rhosts autentication is useless
- * if source routing is accepted. Notice also that if we just dropped
- * source routing here, the other side could use IP spoofing to do
- * rest of the interaction and could still bypass security. So we
- * exit here if we detect any IP options.
+ * Map it back to an IP address and check that the given
+ * address actually is an address of this host. This is
+ * necessary because anyone with access to a name server can
+ * define arbitrary names for an IP address. Mapping from
+ * name to IP address can be trusted better (but can still be
+ * fooled if the intruder has access to the name server of
+ * the domain).
*/
- /* IP options -- IPv4 only */
- if (from.ss_family == AF_INET) {
- u_char options[200], *ucp;
- char text[1024], *cp;
- socklen_t option_size;
- int ipproto;
- struct protoent *ip;
-
- if ((ip = getprotobyname("ip")) != NULL)
- ipproto = ip->p_proto;
- else
- ipproto = IPPROTO_IP;
- option_size = sizeof(options);
- if (getsockopt(socket, ipproto, IP_OPTIONS, (char *) options,
- &option_size) >= 0 && option_size != 0) {
- cp = text;
- /* Note: "text" buffer must be at least 3x as big as options. */
- for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
- sprintf(cp, " %2.2x", *ucp);
- log("Connection from %.100s with IP options:%.800s",
- ntop, text);
- packet_disconnect("Connection from %.100s with IP options:%.800s",
- ntop, text);
- }
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = from.ss_family;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
+ log("reverse mapping checking getaddrinfo for %.700s "
+ "failed - POSSIBLE BREAKIN ATTEMPT!", name);
+ return xstrdup(ntop);
+ }
+ /* Look for the address from the list of addresses. */
+ for (ai = aitop; ai; ai = ai->ai_next) {
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
+ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
+ (strcmp(ntop, ntop2) == 0))
+ break;
+ }
+ freeaddrinfo(aitop);
+ /* If we reached the end of the list, the address was not there. */
+ if (!ai) {
+ /* Address not found for the host name. */
+ log("Address %.100s maps to %.600s, but this does not "
+ "map back to the address - POSSIBLE BREAKIN ATTEMPT!",
+ ntop, name);
+ return xstrdup(ntop);
}
-
return xstrdup(name);
}
/*
+ * If IP options are supported, make sure there are none (log and
+ * disconnect them if any are found). Basically we are worried about
+ * source routing; it can be used to pretend you are somebody
+ * (ip-address) you are not. That itself may be "almost acceptable"
+ * under certain circumstances, but rhosts autentication is useless
+ * if source routing is accepted. Notice also that if we just dropped
+ * source routing here, the other side could use IP spoofing to do
+ * rest of the interaction and could still bypass security. So we
+ * exit here if we detect any IP options.
+ */
+/* IPv4 only */
+void
+check_ip_options(int socket, char *ipaddr)
+{
+ u_char options[200], *ucp;
+ char text[1024], *cp;
+ socklen_t option_size;
+ int ipproto;
+ struct protoent *ip;
+
+ if ((ip = getprotobyname("ip")) != NULL)
+ ipproto = ip->p_proto;
+ else
+ ipproto = IPPROTO_IP;
+ option_size = sizeof(options);
+ if (getsockopt(socket, ipproto, IP_OPTIONS, (void *)options,
+ &option_size) >= 0 && option_size != 0) {
+ cp = text;
+ /* Note: "text" buffer must be at least 3x as big as options. */
+ for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
+ sprintf(cp, " %2.2x", *ucp);
+ log("Connection from %.100s with IP options:%.800s",
+ ipaddr, text);
+ packet_disconnect("Connection from %.100s with IP options:%.800s",
+ ipaddr, text);
+ }
+}
+
+/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
* several times.
*/
const char *
-get_canonical_hostname()
+get_canonical_hostname(int reverse_mapping_check)
{
static char *canonical_host_name = NULL;
+ static int reverse_mapping_checked = 0;
- /* Check if we have previously retrieved this same name. */
- if (canonical_host_name != NULL)
- return canonical_host_name;
+ /* Check if we have previously retrieved name with same option. */
+ if (canonical_host_name != NULL) {
+ if (reverse_mapping_checked != reverse_mapping_check)
+ xfree(canonical_host_name);
+ else
+ return canonical_host_name;
+ }
/* 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());
+ canonical_host_name = get_remote_hostname(
+ packet_get_connection_in(), reverse_mapping_check);
else
canonical_host_name = xstrdup("UNKNOWN");
+ reverse_mapping_checked = reverse_mapping_check;
return canonical_host_name;
}
diff --git a/canohost.h b/canohost.h
index 982ec594..da60b3af 100644
--- a/canohost.h
+++ b/canohost.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.h,v 1.3 2001/01/29 19:42:35 markus Exp $ */
+/* $OpenBSD: canohost.h,v 1.4 2001/02/03 10:08:37 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -11,22 +11,17 @@
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
-/*
- * Returns the name of the machine at the other end of the socket. The
- * returned string should be freed by the caller.
- */
-char *get_remote_hostname(int socket);
/*
* Return the canonical name of the host in the other side of the current
* connection (as returned by packet_get_connection). The host name is
* cached, so it is efficient to call this several times.
*/
-const char *get_canonical_hostname(void);
+const char *get_canonical_hostname(int reverse_mapping_check);
/*
* Returns the IP-address of the remote host as a string. The returned
- * string must not be freed.
+ * string is cached and must not be freed.
*/
const char *get_remote_ipaddr(void);
diff --git a/channels.c b/channels.c
index 82a2db05..d343ac89 100644
--- a/channels.c
+++ b/channels.c
@@ -40,7 +40,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.85 2001/01/29 19:42:35 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.88 2001/02/01 21:58:08 markus Exp $");
#include <openssl/rsa.h>
#include <openssl/dsa.h>
@@ -600,7 +600,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
struct sockaddr addr;
int newsock, newch;
socklen_t addrlen;
- char buf[1024], *remote_hostname, *rtype;
+ char buf[1024], *remote_ipaddr, *rtype;
int remote_port;
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
@@ -616,13 +616,13 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
error("accept: %.100s", strerror(errno));
return;
}
- remote_hostname = get_remote_hostname(newsock);
+ remote_ipaddr = get_peer_ipaddr(newsock);
remote_port = get_peer_port(newsock);
snprintf(buf, sizeof buf,
"listen port %d for %.100s port %d, "
"connect from %.200s port %d",
c->listening_port, c->path, c->host_port,
- remote_hostname, remote_port);
+ remote_ipaddr, remote_port);
newch = channel_new(rtype,
SSH_CHANNEL_OPENING, newsock, newsock, -1,
@@ -644,7 +644,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
packet_put_int(c->host_port);
}
/* originator host and port */
- packet_put_cstring(remote_hostname);
+ packet_put_cstring(remote_ipaddr);
packet_put_int(remote_port);
packet_send();
} else {
@@ -657,7 +657,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
}
packet_send();
}
- xfree(remote_hostname);
+ xfree(remote_ipaddr);
}
}
diff --git a/contrib/caldera/openssh.spec b/contrib/caldera/openssh.spec
index 557770d7..6bba4d36 100644
--- a/contrib/caldera/openssh.spec
+++ b/contrib/caldera/openssh.spec
@@ -253,9 +253,13 @@ fi
%attr(4755,root,root) %{_bindir}/ssh
%attr(0755,root,root) %{_bindir}/ssh-agent
%attr(0755,root,root) %{_bindir}/ssh-add
+%attr(0755,root,root) %{_bindir}/ssh-keyscan
+%attr(0755,root,root) %{_bindir}/sftp
%attr(0644,root,root) %{_mandir}/man1/ssh.1*
%attr(0644,root,root) %{_mandir}/man1/ssh-agent.1*
%attr(0644,root,root) %{_mandir}/man1/ssh-add.1*
+%attr(0644,root,root) %{_mandir}/man1/ssh-keyscan.1*
+%attr(0644,root,root) %{_mandir}/man1/sftp.1*
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh_config
%attr(-,root,root) %{_bindir}/slogin
%attr(-,root,root) %{_mandir}/man1/slogin.1*
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec
index 482306f8..c6574a27 100644
--- a/contrib/redhat/openssh.spec
+++ b/contrib/redhat/openssh.spec
@@ -223,9 +223,13 @@ fi
%attr(4755,root,root) %{_bindir}/ssh
%attr(0755,root,root) %{_bindir}/ssh-agent
%attr(0755,root,root) %{_bindir}/ssh-add
+%attr(0755,root,root) %{_bindir}/ssh-keyscan
+%attr(0755,root,root) %{_bindir}/sftp
%attr(0644,root,root) %{_mandir}/man1/ssh.1*
%attr(0644,root,root) %{_mandir}/man1/ssh-agent.1*
%attr(0644,root,root) %{_mandir}/man1/ssh-add.1*
+%attr(0644,root,root) %{_mandir}/man1/ssh-keyscan.1*
+%attr(0644,root,root) %{_mandir}/man1/sftp.1*
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh_config
%attr(-,root,root) %{_bindir}/slogin
%attr(-,root,root) %{_mandir}/man1/slogin.1*
diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec
index b4cc2d92..01ff204e 100644
--- a/contrib/suse/openssh.spec
+++ b/contrib/suse/openssh.spec
@@ -180,6 +180,8 @@ fi
%attr(-,root,root) /usr/bin/slogin
%attr(0755,root,root) /usr/bin/ssh-agent
%attr(0755,root,root) /usr/bin/ssh-add
+%attr(0755,root,root) /usr/bin/ssh-keyscan
+%attr(0755,root,root) /usr/bin/sftp
%attr(0755,root,root) /usr/sbin/sshd
%attr(-,root,root) /usr/sbin/rcsshd
%attr(0755,root,root) %dir /usr/lib/ssh
diff --git a/scp.1 b/scp.1
index 0a2ca1a3..10e67aa3 100644
--- a/scp.1
+++ b/scp.1
@@ -9,7 +9,7 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
-.\" $OpenBSD: scp.1,v 1.13 2000/10/16 09:38:44 djm Exp $
+.\" $OpenBSD: scp.1,v 1.14 2001/02/04 11:11:53 djm Exp $
.\"
.Dd September 25, 1999
.Dt SCP 1
@@ -129,6 +129,7 @@ program in BSD source code from the Regents of the University of
California.
.Sh SEE ALSO
.Xr rcp 1 ,
+.Xr sftp 1 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
diff --git a/servconf.c b/servconf.c
index 9f292b6a..5fa41e02 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.63 2001/01/22 23:06:39 markus Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.64 2001/02/03 10:08:37 markus Exp $");
#ifdef KRB4
#include <krb.h>
@@ -92,6 +92,7 @@ initialize_server_options(ServerOptions *options)
options->max_startups_rate = -1;
options->max_startups = -1;
options->banner = NULL;
+ options->reverse_mapping_check = -1;
}
void
@@ -186,6 +187,8 @@ 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;
}
/* Keyword tokens. */
@@ -208,7 +211,7 @@ typedef enum {
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
- sBanner
+ sBanner, sReverseMappingCheck
} ServerOpCodes;
/* Textual representation of the tokens. */
@@ -268,6 +271,7 @@ static struct {
{ "subsystem", sSubsystem },
{ "maxstartups", sMaxStartups },
{ "banner", sBanner },
+ { "reversemappingcheck", sReverseMappingCheck },
{ NULL, 0 }
};
@@ -577,6 +581,10 @@ parse_flag:
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);
diff --git a/servconf.h b/servconf.h
index e3163670..e7abb94d 100644
--- a/servconf.h
+++ b/servconf.h
@@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-/* RCSID("$OpenBSD: servconf.h,v 1.35 2001/01/22 23:06:40 markus Exp $"); */
+/* RCSID("$OpenBSD: servconf.h,v 1.36 2001/02/03 10:08:37 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@@ -102,6 +102,7 @@ typedef struct {
int max_startups_rate;
int max_startups;
char *banner; /* SSH-2 banner message */
+ int reverse_mapping_check; /* cross-check ip and dns */
} ServerOptions;
/*
diff --git a/session.c b/session.c
index b6ab8873..51b661af 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.51 2001/01/21 19:05:56 markus Exp $");
+RCSID("$OpenBSD: session.c,v 1.52 2001/02/03 10:08:37 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
@@ -683,7 +683,7 @@ get_remote_name_or_ip(void)
{
static const char *remote = "";
if (utmp_len > 0)
- remote = get_canonical_hostname();
+ remote = get_canonical_hostname(options.reverse_mapping_check);
if (utmp_len == 0 || strlen(remote) > utmp_len)
remote = get_remote_ipaddr();
return remote;
@@ -1061,7 +1061,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
#ifdef HAVE_OSF_SIA
extern char **saved_argv;
extern int saved_argc;
- char *host = get_canonical_hostname ();
+ char *host = get_canonical_hostname(options.reverse_mapping_check);
if (sia_become_user(NULL, saved_argc, saved_argv, host,
pw->pw_name, ttyname, 0, NULL, NULL, SIA_BEU_SETLUID) !=
diff --git a/sftp-client.c b/sftp-client.c
new file mode 100644
index 00000000..458d7364
--- /dev/null
+++ b/sftp-client.c
@@ -0,0 +1,792 @@
+/*
+ * Copyright (c) 2001 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* 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: copy between two remote sites */
+
+#include "includes.h"
+RCSID("$OpenBSD: sftp-client.c,v 1.1 2001/02/04 11:11:54 djm Exp $");
+
+#include "ssh.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "getput.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "atomicio.h"
+#include "pathnames.h"
+
+#include "sftp.h"
+#include "sftp-common.h"
+#include "sftp-client.h"
+
+/* How much data to read/write at at time during copies */
+/* XXX: what should this be? */
+#define COPY_SIZE 8192
+
+void
+send_msg(int fd, Buffer *m)
+{
+ int mlen = buffer_len(m);
+ int len;
+ Buffer oqueue;
+
+ buffer_init(&oqueue);
+ buffer_put_int(&oqueue, mlen);
+ buffer_append(&oqueue, buffer_ptr(m), mlen);
+ buffer_consume(m, mlen);
+
+ len = atomicio(write, fd, buffer_ptr(&oqueue), buffer_len(&oqueue));
+ if (len <= 0)
+ fatal("Couldn't send packet: %s", strerror(errno));
+
+ buffer_free(&oqueue);
+}
+
+void
+get_msg(int fd, Buffer *m)
+{
+ u_int len, msg_len;
+ unsigned char buf[4096];
+
+ len = atomicio(read, fd, buf, 4);
+ if (len != 4)
+ fatal("Couldn't read packet: %s", strerror(errno));
+
+ msg_len = GET_32BIT(buf);
+ if (msg_len > 256 * 1024)
+ fatal("Received message too long %d", msg_len);
+
+ while (msg_len) {
+ len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf)));
+ if (len <= 0)
+ fatal("Couldn't read packet: %s", strerror(errno));
+
+ msg_len -= len;
+ buffer_append(m, buf, len);
+ }
+}
+
+void
+send_string_request(int fd, u_int id, u_int code, char *s,
+ u_int len)
+{
+ Buffer msg;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, code);
+ buffer_put_int(&msg, id);
+ buffer_put_string(&msg, s, len);
+ send_msg(fd, &msg);
+ debug3("Sent message fd %d T:%d I:%d", fd, code, id);
+ buffer_free(&msg);
+}
+
+void
+send_string_attrs_request(int fd, u_int id, u_int code, char *s,
+ u_int len, Attrib *a)
+{
+ Buffer msg;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, code);
+ buffer_put_int(&msg, id);
+ buffer_put_string(&msg, s, len);
+ encode_attrib(&msg, a);
+ send_msg(fd, &msg);
+ debug3("Sent message fd %d T:%d I:%d", fd, code, id);
+ buffer_free(&msg);
+}
+
+u_int
+get_status(int fd, int expected_id)
+{
+ Buffer msg;
+ u_int type, id, status;
+
+ buffer_init(&msg);
+ get_msg(fd, &msg);
+ type = buffer_get_char(&msg);
+ id = buffer_get_int(&msg);
+
+ if (id != expected_id)
+ fatal("ID mismatch (%d != %d)", id, expected_id);
+ if (type != SSH2_FXP_STATUS)
+ fatal("Expected SSH2_FXP_STATUS(%d) packet, got %d",
+ SSH2_FXP_STATUS, type);
+
+ status = buffer_get_int(&msg);
+ buffer_free(&msg);
+
+ debug3("SSH2_FXP_STATUS %d", status);
+
+ return(status);
+}
+
+char *
+get_handle(int fd, u_int expected_id, u_int *len)
+{
+ Buffer msg;
+ u_int type, id;
+ char *handle;
+
+ buffer_init(&msg);
+ get_msg(fd, &msg);
+ type = buffer_get_char(&msg);
+ id = buffer_get_int(&msg);
+
+ if (id != expected_id)
+ fatal("ID mismatch (%d != %d)", id, expected_id);
+ if (type == SSH2_FXP_STATUS) {
+ int status = buffer_get_int(&msg);
+
+ error("Couldn't get handle: %s", fx2txt(status));
+ return(NULL);
+ } else if (type != SSH2_FXP_HANDLE)
+ fatal("Expected SSH2_FXP_HANDLE(%d) packet, got %d",
+ SSH2_FXP_HANDLE, type);
+
+ handle = buffer_get_string(&msg, len);
+ buffer_free(&msg);
+
+ return(handle);
+}
+
+Attrib *
+get_decode_stat(int fd, u_int expected_id)
+{
+ Buffer msg;
+ u_int type, id;
+ Attrib *a;
+
+ buffer_init(&msg);
+ get_msg(fd, &msg);
+
+ type = buffer_get_char(&msg);
+ id = buffer_get_int(&msg);
+
+ debug3("Received stat reply T:%d I:%d", type, id);
+ if (id != expected_id)
+ fatal("ID mismatch (%d != %d)", id, expected_id);
+ if (type == SSH2_FXP_STATUS) {
+ int status = buffer_get_int(&msg);
+
+ error("Couldn't stat remote file: %s", fx2txt(status));
+ return(NULL);
+ } else if (type != SSH2_FXP_ATTRS) {
+ fatal("Expected SSH2_FXP_ATTRS(%d) packet, got %d",
+ SSH2_FXP_ATTRS, type);
+ }
+ a = decode_attrib(&msg);
+ buffer_free(&msg);
+
+ return(a);
+}
+
+int
+do_init(int fd_in, int fd_out)
+{
+ int type, version;
+ Buffer msg;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, SSH2_FXP_INIT);
+ buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
+ send_msg(fd_out, &msg);
+
+ buffer_clear(&msg);
+
+ get_msg(fd_in, &msg);
+
+ /* Expecting a VERSION reply */
+ if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) {
+ error("Invalid packet back from SSH2_FXP_INIT (type %d)",
+ type);
+ buffer_free(&msg);
+ return(-1);
+ }
+ version = buffer_get_int(&msg);
+
+ debug2("Remote version: %d", version);
+
+ /* Check for extensions */
+ while (buffer_len(&msg) > 0) {
+ char *name = buffer_get_string(&msg, NULL);
+ char *value = buffer_get_string(&msg, NULL);
+
+ debug2("Init extension: \"%s\"", name);
+ xfree(name);
+ xfree(value);
+ }
+
+ buffer_free(&msg);
+ return(0);
+}
+
+int
+do_close(int fd_in, int fd_out, char *handle, u_int handle_len)
+{
+ u_int id, status;
+ Buffer msg;
+
+ buffer_init(&msg);
+
+ id = arc4random();
+ buffer_put_char(&msg, SSH2_FXP_CLOSE);
+ buffer_put_int(&msg, id);
+ buffer_put_string(&msg, handle, handle_len);
+ send_msg(fd_out, &msg);
+ debug3("Sent message SSH2_FXP_CLOSE I:%d", id);
+
+ status = get_status(fd_in, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't close file: %s", fx2txt(status));
+
+ buffer_free(&msg);
+
+ return(status);
+}
+
+int
+do_ls(int fd_in, int fd_out, char *path)
+{
+ Buffer msg;
+ u_int type, id, handle_len, i, expected_id;
+ char *handle;
+
+ id = arc4random();
+
+ 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);
+
+ buffer_clear(&msg);
+
+ handle = get_handle(fd_in, id, &handle_len);
+ if (handle == NULL)
+ return(-1);
+
+ for(;;) {
+ int count;
+
+ expected_id = ++id;
+
+ debug3("Sending SSH2_FXP_READDIR I:%d", id);
+
+ buffer_clear(&msg);
+ buffer_put_char(&msg, SSH2_FXP_READDIR);
+ buffer_put_int(&msg, id);
+ buffer_put_string(&msg, handle, handle_len);
+ send_msg(fd_out, &msg);
+
+ buffer_clear(&msg);
+
+ get_msg(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) {
+ int status = buffer_get_int(&msg);
+
+ debug3("Received SSH2_FXP_STATUS %d", status);
+
+ if (status == SSH2_FX_EOF) {
+ break;
+ } else {
+ error("Couldn't read directory: %s",
+ fx2txt(status));
+ do_close(fd_in, fd_out, handle, handle_len);
+ return(NULL);
+ }
+ } else if (type != SSH2_FXP_NAME)
+ fatal("Expected SSH2_FXP_NAME(%d) packet, got %d",
+ SSH2_FXP_NAME, type);
+
+ count = buffer_get_int(&msg);
+ debug3("Received %i SSH2_FXP_NAME responses", count);
+ for(i = 0; i < count; i++) {
+ char *filename, *longname;
+ Attrib *a;
+
+ filename = buffer_get_string(&msg, NULL);
+ longname = buffer_get_string(&msg, NULL);
+ a = decode_attrib(&msg);
+
+ printf("%s\n", longname);
+
+ xfree(filename);
+ xfree(longname);
+ }
+ }
+
+ buffer_free(&msg);
+ do_close(fd_in, fd_out, handle, handle_len);
+ xfree(handle);
+
+ return(0);
+}
+
+int
+do_rm(int fd_in, int fd_out, char *path)
+{
+ u_int status, id;
+
+ debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
+
+ id = arc4random();
+ send_string_request(fd_out, id, SSH2_FXP_REMOVE, path, strlen(path));
+ status = get_status(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)
+{
+ u_int status, id;
+
+ id = arc4random();
+ send_string_attrs_request(fd_out, id, SSH2_FXP_MKDIR, path,
+ strlen(path), a);
+
+ status = get_status(fd_in, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't create directory: %s", fx2txt(status));
+
+ return(status);
+}
+
+int
+do_rmdir(int fd_in, int fd_out, char *path)
+{
+ u_int status, id;
+
+ id = arc4random();
+ send_string_request(fd_out, id, SSH2_FXP_RMDIR, path, strlen(path));
+
+ status = get_status(fd_in, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't remove directory: %s", fx2txt(status));
+
+ return(status);
+}
+
+Attrib *
+do_stat(int fd_in, int fd_out, char *path)
+{
+ u_int id;
+
+ id = arc4random();
+ send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path));
+ return(get_decode_stat(fd_in, id));
+}
+
+Attrib *
+do_lstat(int fd_in, int fd_out, char *path)
+{
+ u_int id;
+
+ id = arc4random();
+ send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path));
+ return(get_decode_stat(fd_in, id));
+}
+
+Attrib *
+do_fstat(int fd_in, int fd_out, char *handle,
+ u_int handle_len)
+{
+ u_int id;
+
+ id = arc4random();
+ send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len);
+ return(get_decode_stat(fd_in, id));
+}
+
+int
+do_setstat(int fd_in, int fd_out, char *path, Attrib *a)
+{
+ u_int status, id;
+
+ id = arc4random();
+ send_string_attrs_request(fd_out, id, SSH2_FXP_SETSTAT, path,
+ strlen(path), a);
+
+ status = get_status(fd_in, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't setstat on \"%s\": %s", path,
+ fx2txt(status));
+
+ return(status);
+}
+
+int
+do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len,
+ Attrib *a)
+{
+ u_int status, id;
+
+ id = arc4random();
+ send_string_attrs_request(fd_out, id, SSH2_FXP_FSETSTAT, handle,
+ handle_len, a);
+
+ status = get_status(fd_in, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't fsetstat: %s", fx2txt(status));
+
+ return(status);
+}
+
+char *
+do_realpath(int fd_in, int fd_out, char *path)
+{
+ Buffer msg;
+ u_int type, expected_id, count, id;
+ char *filename, *longname;
+ Attrib *a;
+
+ expected_id = id = arc4random();
+ send_string_request(fd_out, id, SSH2_FXP_REALPATH, path,
+ strlen(path));
+
+ buffer_init(&msg);
+
+ get_msg(fd_in, &msg);
+ type = buffer_get_char(&msg);
+ id = buffer_get_int(&msg);
+
+ if (id != expected_id)
+ fatal("ID mismatch (%d != %d)", id, expected_id);
+
+ if (type == SSH2_FXP_STATUS) {
+ u_int status = buffer_get_int(&msg);
+
+ error("Couldn't canonicalise: %s", fx2txt(status));
+ return(NULL);
+ } else if (type != SSH2_FXP_NAME)
+ fatal("Expected SSH2_FXP_NAME(%d) packet, got %d",
+ SSH2_FXP_NAME, type);
+
+ count = buffer_get_int(&msg);
+ if (count != 1)
+ fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
+
+ filename = buffer_get_string(&msg, NULL);
+ longname = buffer_get_string(&msg, NULL);
+ a = decode_attrib(&msg);
+
+ debug3("SSH_FXP_REALPATH %s -> %s", path, filename);
+
+ xfree(longname);
+
+ buffer_free(&msg);
+
+ return(filename);
+}
+
+int
+do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)
+{
+ Buffer msg;
+ u_int status, id;
+
+ buffer_init(&msg);
+
+ /* Send rename request */
+ id = arc4random();
+ 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);
+ debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,
+ newpath);
+ buffer_free(&msg);
+
+ status = get_status(fd_in, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath,
+ fx2txt(status));
+
+ return(status);
+}
+
+int
+do_download(int fd_in, int fd_out, 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;
+
+ a = do_stat(fd_in, fd_out, remote_path);
+ if (a == NULL)
+ return(-1);
+
+ /* XXX: should we preserve set[ug]id? */
+ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
+ mode = S_IWRITE | (a->perm & 0777);
+ else
+ mode = 0666;
+
+ 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(errno);
+ }
+
+ /* Override umask and utimes if asked */
+ if (pflag && fchmod(local_fd, mode) == -1)
+ error("Couldn't set mode on \"%s\": %s", local_path,
+ strerror(errno));
+ if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
+ struct timeval tv;
+
+ tv.tv_sec = a->atime;
+ tv.tv_usec = a->mtime;
+ if (utimes(local_path, &tv) == -1)
+ error("Can't set times on \"%s\": %s", local_path,
+ strerror(errno));
+ }
+
+ buffer_init(&msg);
+
+ /* Send open request */
+ id = arc4random();
+ buffer_put_char(&msg, SSH2_FXP_OPEN);
+ buffer_put_int(&msg, id);
+ buffer_put_cstring(&msg, remote_path);
+ buffer_put_int(&msg, SSH2_FXF_READ);
+ attrib_clear(&junk); /* Send empty attributes */
+ encode_attrib(&msg, &junk);
+ send_msg(fd_out, &msg);
+ debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
+
+ handle = get_handle(fd_in, id, &handle_len);
+ if (handle == NULL) {
+ buffer_free(&msg);
+ close(local_fd);
+ return(-1);
+ }
+
+ /* Read from remote and write to local */
+ offset = 0;
+ for(;;) {
+ u_int len;
+ char *data;
+
+ expected_id = ++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, offset, COPY_SIZE);
+
+ buffer_clear(&msg);
+
+ get_msg(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) {
+ int status = buffer_get_int(&msg);
+
+ 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);
+ xfree(handle);
+ close(local_fd);
+ buffer_free(&msg);
+ return(status);
+ }
+ } else if (type != SSH2_FXP_DATA) {
+ 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 %lld", len, 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);
+ xfree(handle);
+ close(local_fd);
+ xfree(data);
+ buffer_free(&msg);
+ return(-1);
+ }
+
+ offset += len;
+ xfree(data);
+ }
+ xfree(handle);
+ buffer_free(&msg);
+ close(local_fd);
+
+ return(do_close(fd_in, fd_out, handle, handle_len));
+}
+
+int
+do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
+ int pflag)
+{
+ int local_fd;
+ u_int handle_len, id;
+ u_int64_t offset;
+ char *handle;
+ Buffer msg;
+ struct stat sb;
+ Attrib a;
+
+ if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
+ error("Couldn't open local file \"%s\" for reading: %s",
+ local_path, strerror(errno));
+ return(-1);
+ }
+ if (fstat(local_fd, &sb) == -1) {
+ error("Couldn't fstat local file \"%s\": %s",
+ local_path, strerror(errno));
+ close(local_fd);
+ return(-1);
+ }
+ stat_to_attrib(&sb, &a);
+
+ a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
+ a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
+ a.perm &= 0777;
+ if (!pflag)
+ a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
+
+ buffer_init(&msg);
+
+ /* Send open request */
+ id = arc4random();
+ buffer_put_char(&msg, SSH2_FXP_OPEN);
+ buffer_put_int(&msg, id);
+ buffer_put_cstring(&msg, remote_path);
+ buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
+ encode_attrib(&msg, &a);
+ send_msg(fd_out, &msg);
+ debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
+
+ buffer_clear(&msg);
+
+ handle = get_handle(fd_in, id, &handle_len);
+ if (handle == NULL) {
+ close(local_fd);
+ buffer_free(&msg);
+ return(-1);
+ }
+
+ /* Override umask and utimes if asked */
+ if (pflag)
+ do_fsetstat(fd_in, fd_out, handle, handle_len, &a);
+
+ /* Read from local and write to remote */
+ offset = 0;
+ for(;;) {
+ int len;
+ char data[COPY_SIZE];
+ u_int status;
+
+ /*
+ * 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);
+ while ((len == -1) && (errno == EINTR || errno == EAGAIN));
+
+ if (len == -1)
+ fatal("Couldn't read from \"%s\": %s", local_path,
+ strerror(errno));
+ if (len == 0)
+ 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, 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);
+ xfree(handle);
+ close(local_fd);
+ return(-1);
+ }
+ debug3("In write loop, got %d offset %lld", len, offset);
+
+ offset += len;
+ }
+ xfree(handle);
+ buffer_free(&msg);
+
+ 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);
+ return(-1);
+ }
+
+ return(do_close(fd_in, fd_out, handle, handle_len));
+}
diff --git a/sftp-client.h b/sftp-client.h
new file mode 100644
index 00000000..838b46b0
--- /dev/null
+++ b/sftp-client.h
@@ -0,0 +1,84 @@
+/* $OpenBSD: sftp-client.h,v 1.1 2001/02/04 11:11:54 djm Exp $ */
+
+/*
+ * Copyright (c) 2001 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Client side of SSH2 filexfer protocol */
+
+/* Initialiase a SSH filexfer connection */
+int do_init(int fd_in, int fd_out);
+
+/* Close file referred to by 'handle' */
+int do_close(int fd_in, int fd_out, char *handle, u_int handle_len);
+
+/* List contents of directory 'path' to stdout */
+int do_ls(int fd_in, int fd_out, char *path);
+
+/* Delete file 'path' */
+int do_rm(int fd_in, int fd_out, char *path);
+
+/* Create directory 'path' */
+int do_mkdir(int fd_in, int fd_out, char *path, Attrib *a);
+
+/* Remove directory 'path' */
+int do_rmdir(int fd_in, int fd_out, char *path);
+
+/* Get file attributes of 'path' (follows symlinks) */
+Attrib *do_stat(int fd_in, int fd_out, char *path);
+
+/* Get file attributes of 'path' (does not follow symlinks) */
+Attrib *do_lstat(int fd_in, int fd_out, char *path);
+
+/* Get file attributes of open file 'handle' */
+Attrib *do_fstat(int fd_in, int fd_out, char *handle,
+ u_int handle_len);
+
+/* Set file attributes of 'path' */
+int do_setstat(int fd_in, int fd_out, char *path, Attrib *a);
+
+/* Set file attributes of open file 'handle' */
+int do_fsetstat(int fd_in, int fd_out, char *handle,
+ u_int handle_len, Attrib *a);
+
+/* Canonicalise 'path' - caller must free result */
+char *do_realpath(int fd_in, int fd_out, char *path);
+
+/* Rename 'oldpath' to 'newpath' */
+int do_rename(int fd_in, int fd_out, char *oldpath, char *newpath);
+
+/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
+
+/*
+ * Download 'remote_path' to 'local_path'. Preserve permissions and times
+ * if 'pflag' is set
+ */
+int do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
+ int pflag);
+
+/*
+ * Upload 'local_path' to 'remote_path'. Preserve permissions and times
+ * if 'pflag' is set
+ */
+int do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
+ int pflag);
diff --git a/sftp-common.c b/sftp-common.c
new file mode 100644
index 00000000..aed9b339
--- /dev/null
+++ b/sftp-common.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2001 Markus Friedl. 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
+ * 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: sftp-common.c,v 1.1 2001/02/04 11:11:54 djm Exp $");
+
+#include "buffer.h"
+#include "bufaux.h"
+#include "getput.h"
+#include "log.h"
+#include "xmalloc.h"
+
+#include "sftp.h"
+#include "sftp-common.h"
+
+void
+attrib_clear(Attrib *a)
+{
+ a->flags = 0;
+ a->size = 0;
+ a->uid = 0;
+ a->gid = 0;
+ a->perm = 0;
+ a->atime = 0;
+ a->mtime = 0;
+}
+
+void
+stat_to_attrib(struct stat *st, Attrib *a)
+{
+ attrib_clear(a);
+ a->flags = 0;
+ a->flags |= SSH2_FILEXFER_ATTR_SIZE;
+ a->size = st->st_size;
+ a->flags |= SSH2_FILEXFER_ATTR_UIDGID;
+ a->uid = st->st_uid;
+ a->gid = st->st_gid;
+ a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
+ a->perm = st->st_mode;
+ a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
+ a->atime = st->st_atime;
+ a->mtime = st->st_mtime;
+}
+
+Attrib *
+decode_attrib(Buffer *b)
+{
+ static Attrib a;
+ attrib_clear(&a);
+ a.flags = buffer_get_int(b);
+ if (a.flags & SSH2_FILEXFER_ATTR_SIZE)
+ a.size = buffer_get_int64(b);
+ if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ a.uid = buffer_get_int(b);
+ a.gid = buffer_get_int(b);
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
+ a.perm = buffer_get_int(b);
+ if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ a.atime = buffer_get_int(b);
+ a.mtime = buffer_get_int(b);
+ }
+ /* vendor-specific extensions */
+ if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) {
+ char *type, *data;
+ int i, count;
+ count = buffer_get_int(b);
+ for (i = 0; i < count; i++) {
+ type = buffer_get_string(b, NULL);
+ data = buffer_get_string(b, NULL);
+ debug3("Got file attribute \"%s\"", type);
+ xfree(type);
+ xfree(data);
+ }
+ }
+ return &a;
+}
+
+void
+encode_attrib(Buffer *b, Attrib *a)
+{
+ buffer_put_int(b, a->flags);
+ if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
+ buffer_put_int64(b, a->size);
+ if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ buffer_put_int(b, a->uid);
+ buffer_put_int(b, a->gid);
+ }
+ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
+ buffer_put_int(b, a->perm);
+ if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ buffer_put_int(b, a->atime);
+ buffer_put_int(b, a->mtime);
+ }
+}
+
+const char *
+fx2txt(int status)
+{
+ switch (status) {
+ case SSH2_FX_OK:
+ return("No Error");
+ case SSH2_FX_EOF:
+ return("End of File");
+ case SSH2_FX_NO_SUCH_FILE:
+ return("No Such File");
+ case SSH2_FX_PERMISSION_DENIED:
+ return("Permission Denied");
+ case SSH2_FX_FAILURE:
+ return("Failure");
+ case SSH2_FX_BAD_MESSAGE:
+ return("Bad message");
+ case SSH2_FX_NO_CONNECTION:
+ return("No connection");
+ case SSH2_FX_CONNECTION_LOST:
+ return("Connection lost");
+ case SSH2_FX_OP_UNSUPPORTED:
+ return("Operation unsupported");
+ default:
+ return("Unknown status");
+ };
+ /* NOTREACHED */
+}
+
diff --git a/sftp-common.h b/sftp-common.h
new file mode 100644
index 00000000..6dc1a32f
--- /dev/null
+++ b/sftp-common.h
@@ -0,0 +1,55 @@
+/* $OpenBSD: sftp-common.h,v 1.1 2001/02/04 11:11:54 djm Exp $ */
+
+/*
+ * Copyright (c) 2001 Markus Friedl. 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
+ * 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.
+ */
+
+typedef struct Attrib Attrib;
+
+/* File attributes */
+struct Attrib {
+ u_int32_t flags;
+ u_int64_t size;
+ u_int32_t uid;
+ u_int32_t gid;
+ u_int32_t perm;
+ u_int32_t atime;
+ u_int32_t mtime;
+};
+
+/* Clear contents of attributes structure */
+void attrib_clear(Attrib *a);
+
+/* Convert from struct stat to filexfer attribs */
+void stat_to_attrib(struct stat *st, Attrib *a);
+
+/* Decode attributes in buffer */
+Attrib *decode_attrib(Buffer *b);
+
+/* Encode attributes to buffer */
+void encode_attrib(Buffer *b, Attrib *a);
+
+/* Convert from SSH2_FX_ status to text error message */
+const char *fx2txt(int status);
+
diff --git a/sftp-int.c b/sftp-int.c
new file mode 100644
index 00000000..f050c098
--- /dev/null
+++ b/sftp-int.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2001 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* XXX: finish implementation of all commands */
+/* XXX: do fnmatch() instead of using raw pathname */
+/* XXX: recursive operations */
+
+#include "includes.h"
+RCSID("$OpenBSD: sftp-int.c,v 1.1 2001/02/04 11:11:54 djm Exp $");
+
+#include "buffer.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "pathnames.h"
+
+#include "sftp.h"
+#include "sftp-common.h"
+#include "sftp-client.h"
+#include "sftp-int.h"
+
+/* Seperators for interactive commands */
+#define WHITESPACE " \t\r\n"
+
+/* Commands for interactive mode */
+#define I_CHDIR 1
+#define I_CHGRP 2
+#define I_CHMOD 3
+#define I_CHOWN 4
+#define I_GET 5
+#define I_HELP 6
+#define I_LCHDIR 7
+#define I_LLS 8
+#define I_LMKDIR 9
+#define I_LPWD 10
+#define I_LS 11
+#define I_LUMASK 12
+#define I_MKDIR 13
+#define I_PUT 14
+#define I_PWD 15
+#define I_QUIT 16
+#define I_RENAME 17
+#define I_RM 18
+#define I_RMDIR 19
+#define I_SHELL 20
+
+struct CMD {
+ const int n;
+ const char *c;
+};
+
+const struct CMD cmds[] = {
+ { I_CHDIR, "CD" },
+ { I_CHDIR, "CHDIR" },
+ { I_CHDIR, "LCD" },
+ { I_CHGRP, "CHGRP" },
+ { I_CHMOD, "CHMOD" },
+ { I_CHOWN, "CHOWN" },
+ { I_HELP, "HELP" },
+ { I_GET, "GET" },
+ { I_LCHDIR, "LCHDIR" },
+ { I_LLS, "LLS" },
+ { I_LMKDIR, "LMKDIR" },
+ { I_LPWD, "LPWD" },
+ { I_LS, "LS" },
+ { I_LUMASK, "LUMASK" },
+ { I_MKDIR, "MKDIR" },
+ { I_PUT, "PUT" },
+ { I_PWD, "PWD" },
+ { I_QUIT, "EXIT" },
+ { I_QUIT, "QUIT" },
+ { I_RENAME, "RENAME" },
+ { I_RMDIR, "RMDIR" },
+ { I_RM, "RM" },
+ { I_SHELL, "!" },
+ { -1, NULL}
+};
+
+void
+help(void)
+{
+ printf("Available commands:\n");
+ printf("CD path Change remote directory to 'path'\n");
+ printf("LCD path Change local directory to 'path'\n");
+ printf("CHGRP grp path Change group of file 'path' to 'grp'\n");
+ printf("CHMOD mode path Change permissions of file 'path' to 'mode'\n");
+ printf("CHOWN own path Change owner of file 'path' to 'own'\n");
+ printf("HELP Display this help text\n");
+ printf("GET remote-path [local-path] Download file\n");
+ printf("LLS [ls options] [path] Display local directory listing\n");
+ printf("LMKDIR path Create local directory\n");
+ printf("LPWD Print local working directory\n");
+ printf("LS [path] Display remote directory listing\n");
+ printf("LUMASK umask Set local umask to 'umask'\n");
+ printf("MKDIR path Create remote directory\n");
+ printf("PUT local-path [remote-path] Upload file\n");
+ printf("PWD Display remote working directory\n");
+ printf("EXIT Quit sftp\n");
+ printf("QUIT Quit sftp\n");
+ printf("RENAME oldpath newpath Rename remote file\n");
+ printf("RMDIR path Remove remote directory\n");
+ printf("RM path Delete remote file\n");
+ printf("!command Execute 'command' in local shell\n");
+ printf("! Escape to local shell\n");
+}
+
+void
+local_do_shell(const char *args)
+{
+ int ret, status;
+ char *shell;
+ pid_t pid;
+
+ if (!*args)
+ args = NULL;
+
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = _PATH_BSHELL;
+
+ if ((pid = fork()) == -1)
+ fatal("Couldn't fork: %s", strerror(errno));
+
+ if (pid == 0) {
+ /* XXX: child has pipe fds to ssh subproc open - issue? */
+ if (args) {
+ debug3("Executing %s -c \"%s\"", shell, args);
+ ret = execl(shell, shell, "-c", args, NULL);
+ } else {
+ debug3("Executing %s", shell);
+ ret = execl(shell, shell, NULL);
+ }
+ fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell,
+ strerror(errno));
+ _exit(1);
+ }
+ if (waitpid(pid, &status, 0) == -1)
+ fatal("Couldn't wait for child: %s", strerror(errno));
+ if (!WIFEXITED(status))
+ error("Shell exited abormally");
+ else if (WEXITSTATUS(status))
+ error("Shell exited with status %d", WEXITSTATUS(status));
+}
+
+void
+local_do_ls(const char *args)
+{
+ if (!args || !*args)
+ local_do_shell("ls");
+ else {
+ char *buf = xmalloc(8 + strlen(args) + 1);
+
+ /* XXX: quoting - rip quoting code from ftp? */
+ sprintf(buf, "/bin/ls %s", args);
+ local_do_shell(buf);
+ }
+}
+
+char *
+make_absolute(char *p, char *pwd)
+{
+ char buf[2048];
+
+ /* Derelativise */
+ if (p && p[0] != '/') {
+ snprintf(buf, sizeof(buf), "%s/%s", pwd, p);
+ xfree(p);
+ p = xstrdup(buf);
+ }
+
+ return(p);
+}
+
+int
+parse_getput_flags(const char **cpp, int *pflag)
+{
+ const char *cp = *cpp;
+
+ /* Check for flags */
+ if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
+ switch (*cp) {
+ case 'P':
+ *pflag = 1;
+ break;
+ default:
+ error("Invalid flag -%c", *cp);
+ return(-1);
+ }
+ cp += 2;
+ *cpp = cp + strspn(cp, WHITESPACE);
+ }
+
+ return(0);
+}
+
+int
+get_pathname(const char **cpp, char **path)
+{
+ const char *quot, *cp = *cpp;
+ int i;
+
+ cp += strspn(cp, WHITESPACE);
+ if (!*cp) {
+ *cpp = cp;
+ *path = NULL;
+ return(0);
+ }
+
+ /* Check for quoted filenames */
+ if (*cp == '\"' || *cp == '\'') {
+ quot = cp++;
+ for(i = 0; cp[i] && cp[i] != *quot; i++)
+ ;
+ if (!cp[i]) {
+ error("Unterminated quote");
+ *path = NULL;
+ return(-1);
+ }
+ if (i == 0) {
+ error("Empty quotes");
+ *path = NULL;
+ return(-1);
+ }
+ *path = xmalloc(i + 1);
+ memcpy(*path, cp, i);
+ (*path)[i] = '\0';
+ cp += i + 1;
+ *cpp = cp + strspn(cp, WHITESPACE);
+ return(0);
+ }
+
+ /* Read to end of filename */
+ for(i = 0; cp[i] && cp[i] != ' '; i++)
+ ;
+
+ *path = xmalloc(i + 1);
+ memcpy(*path, cp, i);
+ (*path)[i] = '\0';
+ cp += i;
+ *cpp = cp + strspn(cp, WHITESPACE);
+
+ return(0);
+}
+
+int
+infer_path(const char *p, char **ifp)
+{
+ char *cp;
+
+ debug("XXX: P = \"%s\"", p);
+
+ cp = strrchr(p, '/');
+
+ if (cp == NULL) {
+ *ifp = xstrdup(p);
+ return(0);
+ }
+
+ if (!cp[1]) {
+ error("Invalid path");
+ return(-1);
+ }
+
+ *ifp = xstrdup(cp + 1);
+ return(0);
+}
+
+int
+parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
+ char **path1, char **path2)
+{
+ const char *cmd, *cp = *cpp;
+ int i, cmdnum;
+
+ /* Skip leading whitespace */
+ cp = cp + strspn(cp, WHITESPACE);
+
+ /* Ignore blank lines */
+ if (!*cp)
+ return(-1);
+
+ /* Figure out which command we have */
+ for(i = 0; cmds[i].c; i++) {
+ int cmdlen = strlen(cmds[i].c);
+
+ /* Check for command followed by whitespace */
+ if (!strncasecmp(cp, cmds[i].c, cmdlen) &&
+ strchr(WHITESPACE, cp[cmdlen])) {
+ cp += cmdlen;
+ cp = cp + strspn(cp, WHITESPACE);
+ break;
+ }
+ }
+ cmdnum = cmds[i].n;
+ cmd = cmds[i].c;
+
+ /* Special case */
+ if (*cp == '!') {
+ cp++;
+ cmdnum = I_SHELL;
+ } else if (cmdnum == -1) {
+ error("Invalid command.");
+ return(-1);
+ }
+
+ /* Get arguments and parse flags */
+ *pflag = *n_arg = 0;
+ *path1 = *path2 = NULL;
+ switch (cmdnum) {
+ case I_GET:
+ case I_PUT:
+ if (parse_getput_flags(&cp, pflag))
+ return(-1);
+ /* Get first pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (*path1 == NULL) {
+ error("You must specify at least one path after a "
+ "%s command.", cmd);
+ return(-1);
+ }
+ /* Try to get second pathname (optional) */
+ if (get_pathname(&cp, path2))
+ return(-1);
+ /* Otherwise try to guess it from first path */
+ if (*path2 == NULL && infer_path(*path1, path2))
+ return(-1);
+ break;
+ case I_RENAME:
+ /* Get first pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (get_pathname(&cp, path2))
+ return(-1);
+ if (!*path1 || !*path2) {
+ error("You must specify two paths after a %s "
+ "command.", cmd);
+ return(-1);
+ }
+ break;
+ case I_RM:
+ case I_MKDIR:
+ case I_RMDIR:
+ case I_CHDIR:
+ case I_LCHDIR:
+ case I_LMKDIR:
+ /* Get pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (*path1 == NULL) {
+ error("You must specify a path after a %s command.",
+ cmd);
+ return(-1);
+ }
+ break;
+ case I_LS:
+ /* Path is optional */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ break;
+ case I_LLS:
+ case I_SHELL:
+ /* Uses the rest of the line */
+ break;
+ case I_LUMASK:
+ case I_CHMOD:
+ case I_CHOWN:
+ case I_CHGRP:
+ /* Get numeric arg (mandatory) */
+ if (*cp < '0' && *cp > '9') {
+ error("You must supply a numeric argument "
+ "to the %s command.", cmd);
+ return(-1);
+ }
+ *n_arg = strtoul(cp, (char**)&cp, 0);
+ if (!*cp || !strchr(WHITESPACE, *cp)) {
+ error("You must supply a numeric argument "
+ "to the %s command.", cmd);
+ return(-1);
+ }
+ cp += strspn(cp, WHITESPACE);
+
+ /* Get pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (*path1 == NULL) {
+ error("You must specify a path after a %s command.",
+ cmd);
+ return(-1);
+ }
+ break;
+ case I_QUIT:
+ case I_PWD:
+ case I_LPWD:
+ case I_HELP:
+ break;
+ default:
+ fatal("Command not implemented");
+ }
+
+ *cpp = cp;
+
+ return(cmdnum);
+}
+
+int
+parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
+{
+ char *path1, *path2;
+ int pflag, cmdnum;
+ unsigned long n_arg;
+ Attrib a, *aa;
+ char path_buf[PATH_MAX];
+
+ path1 = path2 = NULL;
+ cmdnum = parse_args(&cmd, &pflag, &n_arg, &path1, &path2);
+
+ /* Perform command */
+ switch (cmdnum) {
+ case -1:
+ break;
+ case I_GET:
+ path1 = make_absolute(path1, *pwd);
+ do_download(in, out, path1, path2, pflag);
+ break;
+ case I_PUT:
+ path2 = make_absolute(path2, *pwd);
+ do_upload(in, out, path1, path2, pflag);
+ break;
+ case I_RENAME:
+ path1 = make_absolute(path1, *pwd);
+ path2 = make_absolute(path2, *pwd);
+ do_rename(in, out, path1, path2);
+ break;
+ case I_RM:
+ path1 = make_absolute(path1, *pwd);
+ do_rm(in, out, path1);
+ break;
+ case I_MKDIR:
+ path1 = make_absolute(path1, *pwd);
+ attrib_clear(&a);
+ a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
+ a.perm = 0777;
+ do_mkdir(in, out, path1, &a);
+ break;
+ case I_RMDIR:
+ path1 = make_absolute(path1, *pwd);
+ do_rmdir(in, out, path1);
+ break;
+ case I_CHDIR:
+ path1 = make_absolute(path1, *pwd);
+ xfree(*pwd);
+ *pwd = do_realpath(in, out, path1);
+ break;
+ case I_LS:
+ path1 = make_absolute(path1, *pwd);
+ do_ls(in, out, path1?path1:*pwd);
+ break;
+ case I_LCHDIR:
+ if (chdir(path1) == -1)
+ error("Couldn't change local directory to "
+ "\"%s\": %s", path1, strerror(errno));
+ break;
+ case I_LMKDIR:
+ if (mkdir(path1, 0777) == -1)
+ error("Couldn't create local directory to "
+ "\"%s\": %s", path1, strerror(errno));
+ break;
+ case I_LLS:
+ local_do_ls(cmd);
+ break;
+ case I_SHELL:
+ local_do_shell(cmd);
+ break;
+ case I_LUMASK:
+ umask(n_arg);
+ break;
+ case I_CHMOD:
+ path1 = make_absolute(path1, *pwd);
+ attrib_clear(&a);
+ a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
+ a.perm = n_arg;
+ do_setstat(in, out, path1, &a);
+ case I_CHOWN:
+ path1 = make_absolute(path1, *pwd);
+ aa = do_stat(in, out, path1);
+ if (!aa->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ error("Can't get current ownership of "
+ "remote file \"%s\"", path1);
+ break;
+ }
+ aa->uid = n_arg;
+ do_setstat(in, out, path1, aa);
+ break;
+ case I_CHGRP:
+ path1 = make_absolute(path1, *pwd);
+ aa = do_stat(in, out, path1);
+ if (!aa->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ error("Can't get current ownership of "
+ "remote file \"%s\"", path1);
+ break;
+ }
+ aa->gid = n_arg;
+ do_setstat(in, out, path1, aa);
+ break;
+ case I_PWD:
+ printf("Remote working directory: %s\n", *pwd);
+ break;
+ case I_LPWD:
+ if (!getcwd(path_buf, sizeof(path_buf)))
+ error("Couldn't get local cwd: %s\n",
+ strerror(errno));
+ else
+ printf("Local working directory: %s\n",
+ path_buf);
+ break;
+ case I_QUIT:
+ return(-1);
+ case I_HELP:
+ help();
+ break;
+ default:
+ fatal("%d is not implemented", cmdnum);
+ }
+
+ if (path1)
+ xfree(path1);
+ if (path2)
+ xfree(path2);
+
+ return(0);
+}
+
+void
+interactive_loop(int fd_in, int fd_out)
+{
+ char *pwd;
+ char cmd[2048];
+
+ pwd = do_realpath(fd_in, fd_out, ".");
+ if (pwd == NULL)
+ fatal("Need cwd");
+
+ setlinebuf(stdout);
+ setlinebuf(stdin);
+
+ for(;;) {
+ char *cp;
+
+ printf("sftp> ");
+
+ /* XXX: use libedit */
+ if (fgets(cmd, sizeof(cmd), stdin) == NULL) {
+ printf("\n");
+ break;
+ }
+ cp = strrchr(cmd, '\n');
+ if (cp)
+ *cp = '\0';
+ if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd))
+ break;
+ }
+ xfree(pwd);
+}
diff --git a/sftp-int.h b/sftp-int.h
new file mode 100644
index 00000000..234d8003
--- /dev/null
+++ b/sftp-int.h
@@ -0,0 +1,27 @@
+/* $OpenBSD: sftp-int.h,v 1.1 2001/02/04 11:11:54 djm Exp $ */
+
+/*
+ * Copyright (c) 2001 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void interactive_loop(int fd_in, int fd_out);
diff --git a/sftp-server.c b/sftp-server.c
index a3e11ce5..0e004009 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -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.14 2001/01/21 19:05:56 markus Exp $");
+RCSID("$OpenBSD: sftp-server.c,v 1.15 2001/02/04 11:11:54 djm Exp $");
#include "buffer.h"
#include "bufaux.h"
@@ -31,6 +31,7 @@ RCSID("$OpenBSD: sftp-server.c,v 1.14 2001/01/21 19:05:56 markus Exp $");
#include "xmalloc.h"
#include "sftp.h"
+#include "sftp-common.h"
/* helper */
#define get_int64() buffer_get_int64(&iqueue);
@@ -50,22 +51,9 @@ Buffer oqueue;
/* portable attibutes, etc. */
-typedef struct Attrib Attrib;
typedef struct Stat Stat;
-struct Attrib
-{
- u_int32_t flags;
- u_int64_t size;
- u_int32_t uid;
- u_int32_t gid;
- u_int32_t perm;
- u_int32_t atime;
- u_int32_t mtime;
-};
-
-struct Stat
-{
+struct Stat {
char *name;
char *long_name;
Attrib attrib;
@@ -122,90 +110,6 @@ flags_from_portable(int pflags)
return flags;
}
-void
-attrib_clear(Attrib *a)
-{
- a->flags = 0;
- a->size = 0;
- a->uid = 0;
- a->gid = 0;
- a->perm = 0;
- a->atime = 0;
- a->mtime = 0;
-}
-
-Attrib *
-decode_attrib(Buffer *b)
-{
- static Attrib a;
- attrib_clear(&a);
- a.flags = buffer_get_int(b);
- if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
- a.size = buffer_get_int64(b);
- }
- if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
- a.uid = buffer_get_int(b);
- a.gid = buffer_get_int(b);
- }
- if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
- a.perm = buffer_get_int(b);
- }
- if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
- a.atime = buffer_get_int(b);
- a.mtime = buffer_get_int(b);
- }
- /* vendor-specific extensions */
- if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) {
- char *type, *data;
- int i, count;
- count = buffer_get_int(b);
- for (i = 0; i < count; i++) {
- type = buffer_get_string(b, NULL);
- data = buffer_get_string(b, NULL);
- xfree(type);
- xfree(data);
- }
- }
- return &a;
-}
-
-void
-encode_attrib(Buffer *b, Attrib *a)
-{
- buffer_put_int(b, a->flags);
- if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
- buffer_put_int64(b, a->size);
- }
- if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
- buffer_put_int(b, a->uid);
- buffer_put_int(b, a->gid);
- }
- if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
- buffer_put_int(b, a->perm);
- }
- if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
- buffer_put_int(b, a->atime);
- buffer_put_int(b, a->mtime);
- }
-}
-
-void
-stat_to_attrib(struct stat *st, Attrib *a)
-{
- attrib_clear(a);
- a->flags = 0;
- a->flags |= SSH2_FILEXFER_ATTR_SIZE;
- a->size = st->st_size;
- a->flags |= SSH2_FILEXFER_ATTR_UIDGID;
- a->uid = st->st_uid;
- a->gid = st->st_gid;
- a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
- a->perm = st->st_mode;
- a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
- a->atime = st->st_atime;
- a->mtime = st->st_mtime;
-}
-
Attrib *
get_attrib(void)
{
diff --git a/sftp.1 b/sftp.1
new file mode 100644
index 00000000..59206b65
--- /dev/null
+++ b/sftp.1
@@ -0,0 +1,156 @@
+.\" $OpenBSD: sftp.1,v 1.1 2001/02/04 11:11:54 djm Exp $
+.\"
+.\" Copyright (c) 2001 Damien Miller. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd Febuary 4, 2001
+.Dt SFTP 1
+.Os
+.Sh NAME
+.Nm sftp
+.Nd Secure file tranfer program
+.Sh SYNOPSIS
+.Nm sftp
+.Op Fl v Li | Fl C
+.Op Fl o Ar ssh_option
+.Op Ar hostname | user@hostname
+.Sh DESCRIPTION
+.Nm
+is an interactive file transfer program, similar to
+.Xr ftp 1 ,
+which performs all operations over an encrypted
+.Xr ssh 1
+transport.
+It may also use many features of ssh, such as public key authentication and
+compression.
+.Nm
+connects and logs into the specified
+.Ar hostname
+then enters an interactive command mode.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl C
+Enables compression (via ssh's
+.Fl C
+flag)
+.It Fl v
+Raise logging level. This option is also passed to ssh.
+.It Fl o Ar ssh_option
+Specify an option to be directly passed to
+.Xr ssh 1 .
+.El
+.Sh INTERACTIVE COMMANDS
+Once in interactive mode
+.Nm ,
+understands a set of commands similar to those of
+.Xr ftp 1 .
+Commands are case insensitive.
+.Bl -tag -width Ds
+.It Ic CD Ar path
+Change remote directory to
+.Ar path
+.It Ic LCD Ar path
+Change local directory to
+.Ar path
+.It Ic CHGRP Ar grp Ar path
+Change group of file
+.Ar path to
+.Ar grp .
+.Ar grp
+must be numeric.
+.It Ic CHMOD Ar mode Ar path
+Change permissions of file
+.Ar path to
+.Ar mode
+.It Ic CHOWN Ar own Ar path
+Change owner of file
+.Ar path to
+.Ar own .
+.Ar own
+must be a numeric UID.
+.It Ic HELP
+Display help text
+.It Ic GET Ar remote-file Op Ar local-file
+Retrieve the
+.Ar remote-file
+and store it on the local machine.
+If the local
+file name is not specified, it is given the same name it has on the
+remote machine.
+.It Ic LLS Op Ar ls-options Op Ar path
+Display local directory listing of either
+.Ar path
+or current directory if
+.Ar path
+was not specified.
+.It Ic LMKDIR Ar path
+Create local directory specified by
+.Ar path
+.It Ic LPWD
+Print local working directory
+.It Ic LS Op Ar path
+Display remote directory listing of either
+.Ar path
+or current directory, is
+.Ar path not specified.
+.It Ic LUMASK Ar umask
+Set local umask to
+.Ar umask
+.It Ic MKDIR Ar path
+Create remote directory specified by
+.Ar path
+.It Ic PUT local-file Op Ar remote-file
+Upload
+.Ar local-file
+and store it on the remote machine. If the local file name is not specified,
+it is given the same name it has on the local machine.
+.It Ic PWD
+Display remote working directory
+.It Ic EXIT
+Quit sftp
+.It Ic QUIT
+Quit sftp
+.It Ic RENAME Ar oldpath Ar newpath
+Rename remote file from
+.Ar oldpath
+to
+.Ar newpath
+.It Ic RMDIR Ar path
+Remove remote directory specified by
+.Ar path
+.It Ic RM Ar path
+Delete remote file specified by
+.Ar path
+.It Ic ! Ar command
+Execute
+.Ar command
+in local shell
+.It Ic !
+Escape to local shell
+.Sh AUTHORS
+Damien Miller <djm@mindrot.org>
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-keygen 1 ,
+.Xr sshd 8
diff --git a/sftp.c b/sftp.c
new file mode 100644
index 00000000..0dca12d8
--- /dev/null
+++ b/sftp.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2001 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+RCSID("$OpenBSD: sftp.c,v 1.1 2001/02/04 11:11:54 djm Exp $");
+
+/* XXX: commandline mode */
+/* XXX: copy between two remote hosts (commandline) */
+/* XXX: short-form remote directory listings (like 'ls -C') */
+
+#include "buffer.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "pathnames.h"
+
+#include "sftp.h"
+#include "sftp-common.h"
+#include "sftp-client.h"
+#include "sftp-int.h"
+
+void
+connect_to_server(char **args, int *in, int *out, pid_t *sshpid)
+{
+ int c_in, c_out;
+#ifdef USE_PIPES
+ int pin[2], pout[2];
+ if ((pipe(pin) == -1) || (pipe(pout) == -1))
+ fatal("pipe: %s", strerror(errno));
+ *in = pin[0];
+ *out = pout[1];
+ c_in = pout[0];
+ c_out = pin[1];
+#else /* USE_PIPES */
+ int inout[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
+ fatal("socketpair: %s", strerror(errno));
+ *in = *out = inout[0];
+ c_in = c_out = inout[1];
+#endif /* USE_PIPES */
+
+ if ((*sshpid = fork()) == -1)
+ fatal("fork: %s", strerror(errno));
+ else if (*sshpid == 0) {
+ if ((dup2(c_in, STDIN_FILENO) == -1) ||
+ (dup2(c_out, STDOUT_FILENO) == -1)) {
+ fprintf(stderr, "dup2: %s\n", strerror(errno));
+ exit(1);
+ }
+ close(*in);
+ close(*out);
+ close(c_in);
+ close(c_out);
+ execv(_PATH_SSH_PROGRAM, args);
+ fprintf(stderr, "exec: %s", strerror(errno));
+ exit(1);
+ }
+
+ close(c_in);
+ close(c_out);
+}
+
+char **
+make_ssh_args(char *add_arg)
+{
+ static char **args = NULL;
+ static int nargs = 0;
+ char debug_buf[4096];
+ int i;
+
+ /* Init args array */
+ if (args == NULL) {
+ nargs = 4;
+ i = 0;
+ args = xmalloc(sizeof(*args) * nargs);
+ args[i++] = "ssh";
+ args[i++] = "-oProtocol=2";
+ args[i++] = "-s";
+ args[i++] = NULL;
+ }
+
+ /* If asked to add args, then do so and return */
+ if (add_arg) {
+ i = nargs++ - 1;
+ args = xrealloc(args, sizeof(*args) * nargs);
+ args[i++] = add_arg;
+ args[i++] = NULL;
+ return(NULL);
+ }
+
+ /* Otherwise finish up and return the arg array */
+ make_ssh_args("sftp");
+
+ /* XXX: overflow - doesn't grow debug_buf */
+ debug_buf[0] = '\0';
+ for(i = 0; args[i]; i++) {
+ if (i)
+ strlcat(debug_buf, " ", sizeof(debug_buf));
+
+ strlcat(debug_buf, args[i], sizeof(debug_buf));
+ }
+ debug("SSH args \"%s\"", debug_buf);
+
+ return(args);
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: sftp [-vC] [-osshopt=value] [user@]host\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int in, out, i, debug_level, compress_flag;
+ pid_t sshpid;
+ char *cp;
+ LogLevel ll;
+
+ debug_level = compress_flag = 0;
+ for(i = 1; i < argc && argv[i][0] == '-'; i++) {
+ if (!strcmp(argv[i], "-v"))
+ debug_level = MIN(3, debug_level + 1);
+ else if (!strcmp(argv[i], "-C"))
+ compress_flag = 1;
+ else if (!strncmp(argv[i], "-o", 2)) {
+ make_ssh_args(argv[i]);
+ } else {
+ fprintf(stderr, "Unknown option \"%s\"\n", argv[i]);
+ usage();
+ }
+ }
+
+ if (i == argc || argc > (i + 1))
+ usage();
+
+ if ((cp = strchr(argv[i], '@')) == NULL)
+ cp = argv[i];
+ else {
+ *cp = '\0';
+ if (!argv[i][0]) {
+ fprintf(stderr, "Missing username\n");
+ usage();
+ }
+ make_ssh_args("-l");
+ make_ssh_args(argv[i]);
+ cp++;
+ }
+
+ if (!*cp) {
+ fprintf(stderr, "Missing hostname\n");
+ usage();
+ }
+
+ /* Set up logging and debug '-d' arguments to ssh */
+ ll = SYSLOG_LEVEL_INFO;
+ switch (debug_level) {
+ case 1:
+ ll = SYSLOG_LEVEL_DEBUG1;
+ make_ssh_args("-v");
+ break;
+ case 2:
+ ll = SYSLOG_LEVEL_DEBUG2;
+ make_ssh_args("-v");
+ make_ssh_args("-v");
+ break;
+ case 3:
+ ll = SYSLOG_LEVEL_DEBUG3;
+ make_ssh_args("-v");
+ make_ssh_args("-v");
+ make_ssh_args("-v");
+ break;
+ }
+
+ if (compress_flag)
+ make_ssh_args("-C");
+
+ log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
+
+ make_ssh_args(cp);
+
+ fprintf(stderr, "Connecting to %s...\n", cp);
+
+ connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid);
+
+ do_init(in, out);
+
+ interactive_loop(in, out);
+
+ close(in);
+ close(out);
+
+ if (kill(sshpid, SIGHUP) == -1)
+ fatal("Couldn't terminate ssh process: %s", strerror(errno));
+
+ /* XXX: wait? */
+
+ exit(0);
+}
diff --git a/ssh.1 b/ssh.1
index 6f10436a..99fb8c7c 100644
--- a/ssh.1
+++ b/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.80 2001/01/29 12:36:10 djm Exp $
+.\" $OpenBSD: ssh.1,v 1.83 2001/02/04 11:11:55 djm Exp $
.Dd September 25, 1999
.Dt SSH 1
.Os
@@ -753,8 +753,8 @@ Specifies a file to use instead of
.It Cm HostKeyAlias
Specifies an alias that should be used instead of the
real host name when looking up or saving the host key
-the kown_hosts files.
-This option is useful for tunneling ssh connection
+in the known_hosts files.
+This option is useful for tunneling ssh connections
or if you have multiple servers running on a single host.
.It Cm HostName
Specifies the real host name to log into.
@@ -914,8 +914,9 @@ RSA authentication will only be
attempted if the identity file exists, or an authentication agent is
running.
Note that this option applies to protocol version 1 only.
-.It Cm SkeyAuthentication
-Specifies whether to use
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge response authentication.
+Currently there is only support for
.Xr skey 1
authentication.
The argument to this keyword must be
@@ -1270,6 +1271,7 @@ protocol versions 1.5 and 2.0.
.Xr rlogin 1 ,
.Xr rsh 1 ,
.Xr scp 1 ,
+.Xr sftp 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
diff --git a/ssh_config b/ssh_config
index e7dabbf5..cfaf2313 100644
--- a/ssh_config
+++ b/ssh_config
@@ -1,8 +1,8 @@
-# $OpenBSD: ssh_config,v 1.7 2001/01/29 01:58:18 niklas Exp $
+# $OpenBSD: ssh_config,v 1.8 2001/02/02 12:57:51 deraadt Exp $
-# This is ssh client systemwide configuration file. This file provides
-# defaults for users, and the values can be changed in per-user configuration
-# files or on the command line.
+# 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.
# Configuration data is parsed as follows:
# 1. command line options
diff --git a/sshconnect1.c b/sshconnect1.c
index e732806f..80b769b4 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect1.c,v 1.21 2001/01/29 19:47:31 markus Exp $");
+RCSID("$OpenBSD: sshconnect1.c,v 1.22 2001/02/03 10:08:37 markus Exp $");
#include <openssl/bn.h>
#include <openssl/evp.h>
@@ -399,11 +399,11 @@ try_kerberos_authentication()
if (stat(tkt_string(), &st) < 0)
return 0;
- strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
+ strncpy(inst, (char *) krb_get_phost(get_canonical_hostname(1)), INST_SZ);
- realm = (char *) krb_realmofhost(get_canonical_hostname());
+ realm = (char *) krb_realmofhost(get_canonical_hostname(1));
if (!realm) {
- debug("Kerberos V4: no realm for %s", get_canonical_hostname());
+ debug("Kerberos V4: no realm for %s", get_canonical_hostname(1));
return 0;
}
/* This can really be anything. */
diff --git a/sshd.8 b/sshd.8
index 1aad0fc8..c71ecb2a 100644
--- a/sshd.8
+++ b/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.86 2001/01/28 20:43:25 stevesk Exp $
+.\" $OpenBSD: sshd.8,v 1.90 2001/02/04 11:11:55 djm Exp $
.Dd September 25, 1999
.Dt SSHD 8
.Os
@@ -593,6 +593,14 @@ The default is
.It Cm RandomSeed
Obsolete.
Random number generation uses other techniques.
+.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.
@@ -616,15 +624,15 @@ Note that this option applies to protocol version 1 only.
.It Cm ServerKeyBits
Defines the number of bits in the server key.
The minimum value is 512, and the default is 768.
-.It Cm SkeyAuthentication
+.It Cm ChallengeResponseAuthentication
Specifies whether
-.Xr skey 1
+challenge reponse
authentication is allowed.
+Currently there is only support for
+.Xr skey 1
+authentication.
The default is
.Dq yes .
-Note that s/key authentication is enabled only if
-.Cm PasswordAuthentication
-is allowed, too.
.It Cm StrictModes
Specifies whether
.Nm
@@ -797,6 +805,9 @@ authentication.
The command supplied by the user (if any) is ignored.
The command is run on a pty if the connection requests a pty;
otherwise it is run without a tty.
+Note that if you want a 8-bit clean channel,
+you must not request a pty or should specify
+.Cm no-pty .
A quote may be included in the command by quoting it with a backslash.
This option might be useful
to restrict certain RSA keys to perform just a specific operation.
@@ -1076,6 +1087,7 @@ Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
.Sh SEE ALSO
.Xr scp 1 ,
+.Xr sftp 1 ,
.Xr sftp-server 8 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff --git a/sshd_config b/sshd_config
index 25c0ec3f..9ba1789a 100644
--- a/sshd_config
+++ b/sshd_config
@@ -1,6 +1,7 @@
-# $OpenBSD: sshd_config,v 1.27 2001/01/29 01:58:19 niklas Exp $
+# $OpenBSD: sshd_config,v 1.30 2001/02/03 10:19:51 markus Exp $
-# This is ssh server systemwide configuration file.
+# This is the sshd server system-wide configuration file. See sshd(8)
+# for more information.
Port 22
#Protocol 2,1
@@ -39,9 +40,9 @@ RSAAuthentication yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
PermitEmptyPasswords no
+
# Uncomment to disable s/key passwords
-#SkeyAuthentication no
-#KbdInteractiveAuthentication yes
+#ChallengeResposeAuthentication no
# To change Kerberos options
#KerberosAuthentication no
@@ -59,3 +60,4 @@ PermitEmptyPasswords no
#Subsystem sftp /usr/libexec/sftp-server
#MaxStartups 10:30:60
#Banner /etc/issue.net
+#ReverseMappingCheck yes