diff options
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | Makefile.in | 18 | ||||
-rw-r--r-- | README.openssh2 | 17 | ||||
-rw-r--r-- | authfd.c | 3 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | scp.1 | 15 | ||||
-rw-r--r-- | scp.c | 4 | ||||
-rw-r--r-- | session.c | 35 | ||||
-rw-r--r-- | sftp-server.8 | 33 | ||||
-rw-r--r-- | sftp-server.c | 1078 | ||||
-rw-r--r-- | ssh-add.1 | 5 | ||||
-rw-r--r-- | ssh-agent.c | 5 | ||||
-rw-r--r-- | ssh.1 | 4 | ||||
-rw-r--r-- | sshd.8 | 8 | ||||
-rw-r--r-- | sshd_config | 3 |
15 files changed, 1222 insertions, 48 deletions
@@ -1,3 +1,43 @@ | |||
1 | 20000905 | ||
2 | - (djm) Import OpenBSD CVS changes | ||
3 | - markus@cvs.openbsd.org 2000/08/31 15:52:24 | ||
4 | [Makefile sshd.8 sshd_config sftp-server.8 sftp-server.c] | ||
5 | implement a SFTP server. interops with sftp2, scp2 and the windows | ||
6 | client from ssh.com | ||
7 | - markus@cvs.openbsd.org 2000/08/31 15:56:03 | ||
8 | [README.openssh2] | ||
9 | sync | ||
10 | - markus@cvs.openbsd.org 2000/08/31 16:05:42 | ||
11 | [session.c] | ||
12 | Wall | ||
13 | - markus@cvs.openbsd.org 2000/08/31 16:09:34 | ||
14 | [authfd.c ssh-agent.c] | ||
15 | add a flag to SSH2_AGENTC_SIGN_REQUEST for future extensions | ||
16 | - deraadt@cvs.openbsd.org 2000/09/01 09:25:13 | ||
17 | [scp.1 scp.c] | ||
18 | cleanup and fix -S support; stevesk@sweden.hp.com | ||
19 | - markus@cvs.openbsd.org 2000/09/01 16:29:32 | ||
20 | [sftp-server.c] | ||
21 | portability fixes | ||
22 | - markus@cvs.openbsd.org 2000/09/01 16:32:41 | ||
23 | [sftp-server.c] | ||
24 | fix cast; mouring@pconline.com | ||
25 | - itojun@cvs.openbsd.org 2000/09/03 09:23:28 | ||
26 | [ssh-add.1 ssh.1] | ||
27 | add missing .El against .Bl. | ||
28 | - markus@cvs.openbsd.org 2000/09/04 13:03:41 | ||
29 | [session.c] | ||
30 | missing close; ok theo | ||
31 | - markus@cvs.openbsd.org 2000/09/04 13:07:21 | ||
32 | [session.c] | ||
33 | fix get_last_login_time order; from andre@van-veen.de | ||
34 | - markus@cvs.openbsd.org 2000/09/04 13:10:09 | ||
35 | [sftp-server.c] | ||
36 | more cast fixes; from mouring@pconline.com | ||
37 | - markus@cvs.openbsd.org 2000/09/04 13:06:04 | ||
38 | [session.c] | ||
39 | set SSH_ORIGINAL_COMMAND; from Leakin@dfw.nostrum.com, bet@rahul.net | ||
40 | - (djm) Cleanup after import. Fix sftp-server compilation, Makefile | ||
1 | 20000903 | 41 | 20000903 |
2 | - (djm) Fix Redhat init script | 42 | - (djm) Fix Redhat init script |
3 | 43 | ||
diff --git a/Makefile.in b/Makefile.in index 4ceef7043..7eb84ce63 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -15,8 +15,8 @@ DESTDIR= | |||
15 | VPATH=@srcdir@ | 15 | VPATH=@srcdir@ |
16 | 16 | ||
17 | SSH_PROGRAM=@bindir@/ssh | 17 | SSH_PROGRAM=@bindir@/ssh |
18 | ASKPASS_LOCATION=@libexecdir@/ssh | 18 | LIBEXEC=@libexecdir@/ssh |
19 | ASKPASS_PROGRAM=$(ASKPASS_LOCATION)/ssh-askpass | 19 | ASKPASS_PROGRAM=$(LIBEXEC)/ssh-askpass |
20 | 20 | ||
21 | CC=@CC@ | 21 | CC=@CC@ |
22 | LD=@LD@ | 22 | LD=@LD@ |
@@ -32,7 +32,7 @@ LDFLAGS=-L. @LDFLAGS@ | |||
32 | 32 | ||
33 | INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ | 33 | INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ |
34 | 34 | ||
35 | TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) | 35 | TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server $(EXTRA_TARGETS) |
36 | 36 | ||
37 | LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o | 37 | LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o |
38 | 38 | ||
@@ -42,13 +42,13 @@ SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o | |||
42 | 42 | ||
43 | SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o | 43 | SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o |
44 | 44 | ||
45 | TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 | 45 | TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8 |
46 | CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 | 46 | CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 sftp-server.0 |
47 | MANPAGES = @MANTYPE@ | 47 | MANPAGES = @MANTYPE@ |
48 | 48 | ||
49 | CONFIGFILES=sshd_config ssh_config | 49 | CONFIGFILES=sshd_config ssh_config |
50 | 50 | ||
51 | PATHSUBS = -D/etc/ssh_config=$(sysconfdir)/ssh_config -D/etc/known_hosts=$(sysconfdir)/ssh_known_hosts -D/etc/sshd_config=$(sysconfdir)/sshd_config -D/etc/shosts.equiv=$(sysconfdir)/shosts.equiv -D/etc/ssh_host_key=$(sysconfdir)/ssh_host_key -D/var/run/sshd.pid=$(piddir)/sshd.pid | 51 | PATHSUBS = -D/etc/ssh_config=$(sysconfdir)/ssh_config -D/etc/known_hosts=$(sysconfdir)/ssh_known_hosts -D/etc/sshd_config=$(sysconfdir)/sshd_config -D/usr/libexec=$(LIBEXEC) -D/etc/shosts.equiv=$(sysconfdir)/shosts.equiv -D/etc/ssh_host_key=$(sysconfdir)/ssh_host_key -D/var/run/sshd.pid=$(piddir)/sshd.pid |
52 | 52 | ||
53 | FIXPATHSCMD = $(PERL) $(srcdir)/fixpaths $(PATHSUBS) | 53 | FIXPATHSCMD = $(PERL) $(srcdir)/fixpaths $(PATHSUBS) |
54 | 54 | ||
@@ -86,6 +86,9 @@ ssh-agent: libopenbsd-compat.a libssh.a ssh-agent.o log-client.o | |||
86 | ssh-keygen: libopenbsd-compat.a libssh.a ssh-keygen.o log-client.o | 86 | ssh-keygen: libopenbsd-compat.a libssh.a ssh-keygen.o log-client.o |
87 | $(LD) -o $@ ssh-keygen.o log-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) | 87 | $(LD) -o $@ ssh-keygen.o log-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) |
88 | 88 | ||
89 | sftp-server: libopenbsd-compat.a libssh.a sftp-server.o log-server.o | ||
90 | $(LD) -o $@ sftp-server.o log-server.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) | ||
91 | |||
89 | # test driver for the loginrec code - not built by default | 92 | # test driver for the loginrec code - not built by default |
90 | logintest: logintest.o libopenbsd-compat.a libssh.a log-client.o loginrec.o | 93 | logintest: logintest.o libopenbsd-compat.a libssh.a log-client.o loginrec.o |
91 | $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh log-client.o $(LIBS) | 94 | $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh log-client.o $(LIBS) |
@@ -123,18 +126,21 @@ install-files: | |||
123 | ./mkinstalldirs $(DESTDIR)$(mandir) | 126 | ./mkinstalldirs $(DESTDIR)$(mandir) |
124 | ./mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1 | 127 | ./mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1 |
125 | ./mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8 | 128 | ./mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8 |
129 | ./mkinstalldirs $(DESTDIR)$(LIBEXEC) | ||
126 | $(INSTALL) -m 4755 -s ssh $(DESTDIR)$(bindir)/ssh | 130 | $(INSTALL) -m 4755 -s ssh $(DESTDIR)$(bindir)/ssh |
127 | $(INSTALL) -m 0755 -s scp $(DESTDIR)$(bindir)/scp | 131 | $(INSTALL) -m 0755 -s scp $(DESTDIR)$(bindir)/scp |
128 | $(INSTALL) -m 0755 -s ssh-add $(DESTDIR)$(bindir)/ssh-add | 132 | $(INSTALL) -m 0755 -s ssh-add $(DESTDIR)$(bindir)/ssh-add |
129 | $(INSTALL) -m 0755 -s ssh-agent $(DESTDIR)$(bindir)/ssh-agent | 133 | $(INSTALL) -m 0755 -s ssh-agent $(DESTDIR)$(bindir)/ssh-agent |
130 | $(INSTALL) -m 0755 -s ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen | 134 | $(INSTALL) -m 0755 -s ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen |
131 | $(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd | 135 | $(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd |
136 | $(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(LIBEXEC)/sftp-server | ||
132 | $(INSTALL) -m 644 ssh.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 | 137 | $(INSTALL) -m 644 ssh.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 |
133 | $(INSTALL) -m 644 scp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 | 138 | $(INSTALL) -m 644 scp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 |
134 | $(INSTALL) -m 644 ssh-add.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 | 139 | $(INSTALL) -m 644 ssh-add.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 |
135 | $(INSTALL) -m 644 ssh-agent.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 | 140 | $(INSTALL) -m 644 ssh-agent.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 |
136 | $(INSTALL) -m 644 ssh-keygen.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 | 141 | $(INSTALL) -m 644 ssh-keygen.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 |
137 | $(INSTALL) -m 644 sshd.[08].out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 | 142 | $(INSTALL) -m 644 sshd.[08].out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 |
143 | $(INSTALL) -m 644 sftp-server.[08].out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 | ||
138 | -rm -f $(DESTDIR)$(bindir)/slogin | 144 | -rm -f $(DESTDIR)$(bindir)/slogin |
139 | ln -s ssh $(DESTDIR)$(bindir)/slogin | 145 | ln -s ssh $(DESTDIR)$(bindir)/slogin |
140 | -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 | 146 | -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 |
diff --git a/README.openssh2 b/README.openssh2 index 12c90aa31..df737c695 100644 --- a/README.openssh2 +++ b/README.openssh2 | |||
@@ -1,4 +1,4 @@ | |||
1 | $Id: README.openssh2,v 1.8 2000/05/07 18:30:03 markus Exp $ | 1 | $Id: README.openssh2,v 1.9 2000/08/31 21:56:03 markus Exp $ |
2 | 2 | ||
3 | howto: | 3 | howto: |
4 | 1) generate server key: | 4 | 1) generate server key: |
@@ -15,30 +15,27 @@ howto: | |||
15 | 15 | ||
16 | works: | 16 | works: |
17 | secsh-transport: works w/o rekey | 17 | secsh-transport: works w/o rekey |
18 | proposal exchange, i.e. different enc/mac/comp per direction | ||
19 | encryption: blowfish-cbc, 3des-cbc, arcfour, cast128-cbc | ||
20 | mac: hmac-md5, hmac-sha1, (hmac-ripemd160) | ||
21 | compression: zlib, none | ||
22 | secsh-userauth: passwd and pubkey with DSA | 18 | secsh-userauth: passwd and pubkey with DSA |
23 | secsh-connection: pty+shell or command, flow control works (window adjust) | 19 | secsh-connection: pty+shell or command, flow control works (window adjust) |
24 | tcp-forwarding: -L works, -R incomplete | 20 | tcp-forwarding: -L works, -R incomplete |
25 | x11-fwd | 21 | x11-fwd |
26 | dss/dsa: host key database in ~/.ssh/known_hosts2 | 22 | dss/dsa: host key database in ~/.ssh/known_hosts2 |
23 | ssh-agent: supports SSH1-RSA and ssh-dss keys | ||
27 | client interops w/ sshd2, lshd | 24 | client interops w/ sshd2, lshd |
28 | server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT, F-Secure SSH Client 4.0, SecureFX (secure ftp) | 25 | server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT, F-Secure SSH Client 4.0, SecureFX (secure ftp) |
29 | server supports multiple concurrent sessions (e.g. with SSH.com Windows client) | 26 | server supports multiple concurrent sessions (e.g. with SSH.com Windows client) |
27 | server supports SFTP (interops with ssh.com's windows, sftp2, scp2) | ||
30 | todo: | 28 | todo: |
31 | re-keying | 29 | RE-KEYING |
32 | secsh-connection features: | 30 | secsh-connection features: |
33 | tcp-forwarding, agent-fwd | 31 | complete tcp-forwarding, agent-fwd |
34 | auth other than passwd, and DSA-pubkey: | 32 | auth other than passwd, and DSA-pubkey: |
35 | keyboard-interactive, (PGP-pubkey?) | 33 | keyboard-interactive, (PGP-pubkey?), kerberos |
36 | config | 34 | config |
37 | server-auth w/ old host-keys | 35 | server-auth w/ old host-keys |
38 | cleanup | 36 | cleanup |
39 | advanced key storage? | 37 | advanced key storage? |
40 | keynote | 38 | keynote |
41 | sftp | ||
42 | 39 | ||
43 | -markus | 40 | -markus |
44 | $Date: 2000/05/07 18:30:03 $ | 41 | $Date: 2000/08/31 21:56:03 $ |
@@ -17,7 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include "includes.h" | 19 | #include "includes.h" |
20 | RCSID("$OpenBSD: authfd.c,v 1.25 2000/08/19 21:34:42 markus Exp $"); | 20 | RCSID("$OpenBSD: authfd.c,v 1.26 2000/08/31 22:09:34 markus Exp $"); |
21 | 21 | ||
22 | #include "ssh.h" | 22 | #include "ssh.h" |
23 | #include "rsa.h" | 23 | #include "rsa.h" |
@@ -359,6 +359,7 @@ ssh_agent_sign(AuthenticationConnection *auth, | |||
359 | buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); | 359 | buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); |
360 | buffer_put_string(&msg, blob, blen); | 360 | buffer_put_string(&msg, blob, blen); |
361 | buffer_put_string(&msg, data, datalen); | 361 | buffer_put_string(&msg, data, datalen); |
362 | buffer_put_int(&msg, 0); /* flags, unused */ | ||
362 | xfree(blob); | 363 | xfree(blob); |
363 | 364 | ||
364 | if (ssh_request_reply(auth, &msg, &msg) == 0) { | 365 | if (ssh_request_reply(auth, &msg, &msg) == 0) { |
diff --git a/configure.in b/configure.in index 33b82895b..b1dd1d067 100644 --- a/configure.in +++ b/configure.in | |||
@@ -235,7 +235,7 @@ fi | |||
235 | AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h) | 235 | AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h) |
236 | 236 | ||
237 | dnl Checks for library functions. | 237 | dnl Checks for library functions. |
238 | AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid sigaction sigvec snprintf strerror strlcat strlcpy strsep vsnprintf vhangup _getpty __b64_ntop) | 238 | AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock freeaddrinfo futimes gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid sigaction sigvec snprintf strerror strlcat strlcpy strsep vsnprintf vhangup _getpty __b64_ntop) |
239 | dnl Checks for time functions | 239 | dnl Checks for time functions |
240 | AC_CHECK_FUNCS(gettimeofday time) | 240 | AC_CHECK_FUNCS(gettimeofday time) |
241 | dnl Checks for libutil functions | 241 | dnl Checks for libutil functions |
@@ -9,7 +9,7 @@ | |||
9 | .\" | 9 | .\" |
10 | .\" Created: Sun May 7 00:14:37 1995 ylo | 10 | .\" Created: Sun May 7 00:14:37 1995 ylo |
11 | .\" | 11 | .\" |
12 | .\" $Id: scp.1,v 1.9 2000/08/23 00:46:24 djm Exp $ | 12 | .\" $Id: scp.1,v 1.10 2000/09/05 02:34:54 djm Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd September 25, 1999 | 14 | .Dd September 25, 1999 |
15 | .Dt SCP 1 | 15 | .Dt SCP 1 |
@@ -20,6 +20,7 @@ | |||
20 | .Sh SYNOPSIS | 20 | .Sh SYNOPSIS |
21 | .Nm scp | 21 | .Nm scp |
22 | .Op Fl pqrvC46 | 22 | .Op Fl pqrvC46 |
23 | .Op Fl S Ar program | ||
23 | .Op Fl P Ar port | 24 | .Op Fl P Ar port |
24 | .Op Fl c Ar cipher | 25 | .Op Fl c Ar cipher |
25 | .Op Fl i Ar identity_file | 26 | .Op Fl i Ar identity_file |
@@ -68,11 +69,6 @@ This option is directly passed to | |||
68 | .It Fl p | 69 | .It Fl p |
69 | Preserves modification times, access times, and modes from the | 70 | Preserves modification times, access times, and modes from the |
70 | original file. | 71 | original file. |
71 | .It Fl S | ||
72 | Name of program to use for the encrypted connection. | ||
73 | The program must understand | ||
74 | .Xr ssh 1 | ||
75 | options. | ||
76 | .It Fl r | 72 | .It Fl r |
77 | Recursively copy entire directories. | 73 | Recursively copy entire directories. |
78 | .It Fl v | 74 | .It Fl v |
@@ -103,9 +99,10 @@ because | |||
103 | .Fl p | 99 | .Fl p |
104 | is already reserved for preserving the times and modes of the file in | 100 | is already reserved for preserving the times and modes of the file in |
105 | .Xr rcp 1 . | 101 | .Xr rcp 1 . |
106 | .It Fl S | 102 | .It Fl S Ar program |
107 | Name of program to use for the encrypted connection. The program must | 103 | Name of |
108 | understand | 104 | .Ar program |
105 | to use for the encrypted connection. The program must understand | ||
109 | .Xr ssh 1 | 106 | .Xr ssh 1 |
110 | options. | 107 | options. |
111 | .It Fl 4 | 108 | .It Fl 4 |
@@ -47,7 +47,7 @@ | |||
47 | */ | 47 | */ |
48 | 48 | ||
49 | #include "includes.h" | 49 | #include "includes.h" |
50 | RCSID("$OpenBSD: scp.c,v 1.36 2000/08/24 21:46:59 deraadt Exp $"); | 50 | RCSID("$OpenBSD: scp.c,v 1.37 2000/09/01 15:25:13 deraadt Exp $"); |
51 | 51 | ||
52 | #include "ssh.h" | 52 | #include "ssh.h" |
53 | #include "xmalloc.h" | 53 | #include "xmalloc.h" |
@@ -262,7 +262,7 @@ main(argc, argv) | |||
262 | extern int optind; | 262 | extern int optind; |
263 | 263 | ||
264 | fflag = tflag = 0; | 264 | fflag = tflag = 0; |
265 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S")) != EOF) | 265 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:")) != EOF) |
266 | switch (ch) { | 266 | switch (ch) { |
267 | /* User-visible flags. */ | 267 | /* User-visible flags. */ |
268 | case '4': | 268 | case '4': |
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "includes.h" | 10 | #include "includes.h" |
11 | RCSID("$OpenBSD: session.c,v 1.31 2000/08/28 03:50:54 deraadt Exp $"); | 11 | RCSID("$OpenBSD: session.c,v 1.35 2000/09/04 19:07:21 markus Exp $"); |
12 | 12 | ||
13 | #include "xmalloc.h" | 13 | #include "xmalloc.h" |
14 | #include "ssh.h" | 14 | #include "ssh.h" |
@@ -113,6 +113,9 @@ extern int startup_pipe; | |||
113 | /* Local Xauthority file. */ | 113 | /* Local Xauthority file. */ |
114 | static char *xauthfile; | 114 | static char *xauthfile; |
115 | 115 | ||
116 | /* original command from peer. */ | ||
117 | char *original_command = NULL; | ||
118 | |||
116 | /* data */ | 119 | /* data */ |
117 | #define MAX_SESSIONS 10 | 120 | #define MAX_SESSIONS 10 |
118 | Session sessions[MAX_SESSIONS]; | 121 | Session sessions[MAX_SESSIONS]; |
@@ -177,7 +180,7 @@ void | |||
177 | do_authenticated(struct passwd * pw) | 180 | do_authenticated(struct passwd * pw) |
178 | { | 181 | { |
179 | Session *s; | 182 | Session *s; |
180 | int type; | 183 | int type, fd; |
181 | int compression_level = 0, enable_compression_after_reply = 0; | 184 | int compression_level = 0, enable_compression_after_reply = 0; |
182 | int have_pty = 0; | 185 | int have_pty = 0; |
183 | char *command; | 186 | char *command; |
@@ -332,7 +335,9 @@ do_authenticated(struct passwd * pw) | |||
332 | break; | 335 | break; |
333 | } | 336 | } |
334 | strlcat(xauthfile, "/cookies", MAXPATHLEN); | 337 | strlcat(xauthfile, "/cookies", MAXPATHLEN); |
335 | open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); | 338 | fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); |
339 | if (fd >= 0) | ||
340 | close(fd); | ||
336 | restore_uid(); | 341 | restore_uid(); |
337 | fatal_add_cleanup(xauthfile_cleanup_proc, NULL); | 342 | fatal_add_cleanup(xauthfile_cleanup_proc, NULL); |
338 | success = 1; | 343 | success = 1; |
@@ -377,6 +382,7 @@ do_authenticated(struct passwd * pw) | |||
377 | packet_integrity_check(plen, 0, type); | 382 | packet_integrity_check(plen, 0, type); |
378 | } | 383 | } |
379 | if (forced_command != NULL) { | 384 | if (forced_command != NULL) { |
385 | original_command = command; | ||
380 | command = forced_command; | 386 | command = forced_command; |
381 | debug("Forced command '%.500s'", forced_command); | 387 | debug("Forced command '%.500s'", forced_command); |
382 | } | 388 | } |
@@ -638,6 +644,7 @@ do_login(Session *s) | |||
638 | FILE *f; | 644 | FILE *f; |
639 | char *time_string; | 645 | char *time_string; |
640 | char buf[256]; | 646 | char buf[256]; |
647 | char hostname[MAXHOSTNAMELEN]; | ||
641 | socklen_t fromlen; | 648 | socklen_t fromlen; |
642 | struct sockaddr_storage from; | 649 | struct sockaddr_storage from; |
643 | struct stat st; | 650 | struct stat st; |
@@ -659,6 +666,10 @@ do_login(Session *s) | |||
659 | } | 666 | } |
660 | } | 667 | } |
661 | 668 | ||
669 | /* Get the time and hostname when the user last logged in. */ | ||
670 | last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, | ||
671 | hostname, sizeof(hostname)); | ||
672 | |||
662 | /* Record that there was a login on that tty from the remote host. */ | 673 | /* Record that there was a login on that tty from the remote host. */ |
663 | record_login(pid, s->tty, pw->pw_name, pw->pw_uid, | 674 | record_login(pid, s->tty, pw->pw_name, pw->pw_uid, |
664 | get_remote_name_or_ip(), (struct sockaddr *)&from); | 675 | get_remote_name_or_ip(), (struct sockaddr *)&from); |
@@ -680,12 +691,6 @@ do_login(Session *s) | |||
680 | printf("%s\n", aixloginmsg); | 691 | printf("%s\n", aixloginmsg); |
681 | #endif /* WITH_AIXAUTHENTICATE */ | 692 | #endif /* WITH_AIXAUTHENTICATE */ |
682 | 693 | ||
683 | /* | ||
684 | * Get the time when the user last logged in. 'buf' will be set | ||
685 | * to contain the hostname the last login was from. | ||
686 | */ | ||
687 | last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, | ||
688 | buf, sizeof(buf)); | ||
689 | if (last_login_time != 0) { | 694 | if (last_login_time != 0) { |
690 | time_string = ctime(&last_login_time); | 695 | time_string = ctime(&last_login_time); |
691 | if (strchr(time_string, '\n')) | 696 | if (strchr(time_string, '\n')) |
@@ -911,7 +916,7 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
911 | const char *display, const char *auth_proto, | 916 | const char *display, const char *auth_proto, |
912 | const char *auth_data, const char *ttyname) | 917 | const char *auth_data, const char *ttyname) |
913 | { | 918 | { |
914 | const char *shell, *hostname, *cp = NULL; | 919 | const char *shell, *hostname = NULL, *cp = NULL; |
915 | char buf[256]; | 920 | char buf[256]; |
916 | char cmd[1024]; | 921 | char cmd[1024]; |
917 | FILE *f = NULL; | 922 | FILE *f = NULL; |
@@ -1089,6 +1094,9 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
1089 | child_set_env(&env, &envsize, "TERM", term); | 1094 | child_set_env(&env, &envsize, "TERM", term); |
1090 | if (display) | 1095 | if (display) |
1091 | child_set_env(&env, &envsize, "DISPLAY", display); | 1096 | child_set_env(&env, &envsize, "DISPLAY", display); |
1097 | if (original_command) | ||
1098 | child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", | ||
1099 | original_command); | ||
1092 | 1100 | ||
1093 | #ifdef _AIX | 1101 | #ifdef _AIX |
1094 | { | 1102 | { |
@@ -1511,6 +1519,7 @@ session_subsystem_req(Session *s) | |||
1511 | int | 1519 | int |
1512 | session_x11_req(Session *s) | 1520 | session_x11_req(Session *s) |
1513 | { | 1521 | { |
1522 | int fd; | ||
1514 | if (no_x11_forwarding_flag) { | 1523 | if (no_x11_forwarding_flag) { |
1515 | debug("X11 forwarding disabled in user configuration file."); | 1524 | debug("X11 forwarding disabled in user configuration file."); |
1516 | return 0; | 1525 | return 0; |
@@ -1555,7 +1564,9 @@ session_x11_req(Session *s) | |||
1555 | return 0; | 1564 | return 0; |
1556 | } | 1565 | } |
1557 | strlcat(xauthfile, "/cookies", MAXPATHLEN); | 1566 | strlcat(xauthfile, "/cookies", MAXPATHLEN); |
1558 | open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); | 1567 | fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); |
1568 | if (fd >= 0) | ||
1569 | close(fd); | ||
1559 | restore_uid(); | 1570 | restore_uid(); |
1560 | fatal_add_cleanup(xauthfile_cleanup_proc, s); | 1571 | fatal_add_cleanup(xauthfile_cleanup_proc, s); |
1561 | return 1; | 1572 | return 1; |
@@ -1582,7 +1593,7 @@ session_exec_req(Session *s) | |||
1582 | char *command = packet_get_string(&len); | 1593 | char *command = packet_get_string(&len); |
1583 | packet_done(); | 1594 | packet_done(); |
1584 | if (forced_command) { | 1595 | if (forced_command) { |
1585 | xfree(command); | 1596 | original_command = command; |
1586 | command = forced_command; | 1597 | command = forced_command; |
1587 | debug("Forced command '%.500s'", forced_command); | 1598 | debug("Forced command '%.500s'", forced_command); |
1588 | } | 1599 | } |
diff --git a/sftp-server.8 b/sftp-server.8 new file mode 100644 index 000000000..85720a082 --- /dev/null +++ b/sftp-server.8 | |||
@@ -0,0 +1,33 @@ | |||
1 | .\" $OpenBSD: sftp-server.8,v 1.1 2000/08/31 21:52:23 markus Exp $ | ||
2 | .Dd August 30, 2000 | ||
3 | .Dt SFTP-SERVER 8 | ||
4 | .Os | ||
5 | .Sh NAME | ||
6 | .Nm sftp-server | ||
7 | .Nd SFTP server subsystem | ||
8 | .Sh SYNOPSIS | ||
9 | .Nm sftp-server | ||
10 | .Sh DESCRIPTION | ||
11 | .Nm | ||
12 | is a program that speaks the server side of SFTP protocol | ||
13 | to stdout and expects client requests from stdin. | ||
14 | .Nm | ||
15 | is not intended to be called directly, but from | ||
16 | .Xr sshd 8 | ||
17 | using the | ||
18 | .Cm Subsystem | ||
19 | option. | ||
20 | See | ||
21 | .Xr sshd 8 | ||
22 | for more information. | ||
23 | .Sh HISTORY | ||
24 | .Nm | ||
25 | first appeared in | ||
26 | .Ox 2.8 . | ||
27 | .Sh AUTHOR | ||
28 | Markus Friedl <markus@openbsd.org> | ||
29 | .Sh SEE ALSO | ||
30 | .Xr ssh 1 , | ||
31 | .Xr ssh-add 1 , | ||
32 | .Xr ssh-keygen 1 , | ||
33 | .Xr sshd 8 , | ||
diff --git a/sftp-server.c b/sftp-server.c new file mode 100644 index 000000000..39cecac59 --- /dev/null +++ b/sftp-server.c | |||
@@ -0,0 +1,1078 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
3 | * | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * 1. Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * 2. Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * 3. All advertising materials mentioning features or use of this software | ||
13 | * must display the following acknowledgement: | ||
14 | * This product includes software developed by Markus Friedl. | ||
15 | * 4. The name of the author may not be used to endorse or promote products | ||
16 | * derived from this software without specific prior written permission. | ||
17 | * | ||
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | #include "includes.h" | ||
30 | RCSID("$OpenBSD: sftp-server.c,v 1.4 2000/09/04 19:10:08 markus Exp $"); | ||
31 | |||
32 | #include "ssh.h" | ||
33 | #include "buffer.h" | ||
34 | #include "bufaux.h" | ||
35 | #include "getput.h" | ||
36 | #include "xmalloc.h" | ||
37 | |||
38 | /* version */ | ||
39 | #define SSH_FILEXFER_VERSION 2 | ||
40 | |||
41 | /* client to server */ | ||
42 | #define SSH_FXP_INIT 1 | ||
43 | #define SSH_FXP_OPEN 3 | ||
44 | #define SSH_FXP_CLOSE 4 | ||
45 | #define SSH_FXP_READ 5 | ||
46 | #define SSH_FXP_WRITE 6 | ||
47 | #define SSH_FXP_LSTAT 7 | ||
48 | #define SSH_FXP_FSTAT 8 | ||
49 | #define SSH_FXP_SETSTAT 9 | ||
50 | #define SSH_FXP_FSETSTAT 10 | ||
51 | #define SSH_FXP_OPENDIR 11 | ||
52 | #define SSH_FXP_READDIR 12 | ||
53 | #define SSH_FXP_REMOVE 13 | ||
54 | #define SSH_FXP_MKDIR 14 | ||
55 | #define SSH_FXP_RMDIR 15 | ||
56 | #define SSH_FXP_REALPATH 16 | ||
57 | #define SSH_FXP_STAT 17 | ||
58 | #define SSH_FXP_RENAME 18 | ||
59 | |||
60 | /* server to client */ | ||
61 | #define SSH_FXP_VERSION 2 | ||
62 | #define SSH_FXP_STATUS 101 | ||
63 | #define SSH_FXP_HANDLE 102 | ||
64 | #define SSH_FXP_DATA 103 | ||
65 | #define SSH_FXP_NAME 104 | ||
66 | #define SSH_FXP_ATTRS 105 | ||
67 | |||
68 | /* portable open modes */ | ||
69 | #define SSH_FXF_READ 0x01 | ||
70 | #define SSH_FXF_WRITE 0x02 | ||
71 | #define SSH_FXF_APPEND 0x04 | ||
72 | #define SSH_FXF_CREAT 0x08 | ||
73 | #define SSH_FXF_TRUNC 0x10 | ||
74 | #define SSH_FXF_EXCL 0x20 | ||
75 | |||
76 | /* attributes */ | ||
77 | #define SSH_FXA_HAVE_SIZE 0x01 | ||
78 | #define SSH_FXA_HAVE_UGID 0x02 | ||
79 | #define SSH_FXA_HAVE_PERM 0x04 | ||
80 | #define SSH_FXA_HAVE_TIME 0x08 | ||
81 | |||
82 | /* status messages */ | ||
83 | #define SSH_FX_OK 0x00 | ||
84 | #define SSH_FX_EOF 0x01 | ||
85 | #define SSH_FX_NO_SUCH_FILE 0x02 | ||
86 | #define SSH_FX_PERMISSION_DENIED 0x03 | ||
87 | #define SSH_FX_FAILURE 0x04 | ||
88 | #define SSH_FX_BAD_MESSAGE 0x05 | ||
89 | #define SSH_FX_NO_CONNECTION 0x06 | ||
90 | #define SSH_FX_CONNECTION_LOST 0x07 | ||
91 | |||
92 | |||
93 | /* helper */ | ||
94 | #define get_int() buffer_get_int(&iqueue); | ||
95 | #define get_string(lenp) buffer_get_string(&iqueue, lenp); | ||
96 | #define TRACE log | ||
97 | |||
98 | /* input and output queue */ | ||
99 | Buffer iqueue; | ||
100 | Buffer oqueue; | ||
101 | |||
102 | /* portable attibutes, etc. */ | ||
103 | |||
104 | typedef struct Attrib Attrib; | ||
105 | typedef struct Stat Stat; | ||
106 | |||
107 | struct Attrib | ||
108 | { | ||
109 | u_int32_t flags; | ||
110 | u_int32_t size_high; | ||
111 | u_int32_t size_low; | ||
112 | u_int64_t size; | ||
113 | u_int32_t uid; | ||
114 | u_int32_t gid; | ||
115 | u_int32_t perm; | ||
116 | u_int32_t atime; | ||
117 | u_int32_t mtime; | ||
118 | }; | ||
119 | |||
120 | struct Stat | ||
121 | { | ||
122 | char *name; | ||
123 | char *long_name; | ||
124 | Attrib attrib; | ||
125 | }; | ||
126 | |||
127 | int | ||
128 | errno_to_portable(int unixerrno) | ||
129 | { | ||
130 | int ret = 0; | ||
131 | switch (unixerrno) { | ||
132 | case 0: | ||
133 | ret = SSH_FX_OK; | ||
134 | break; | ||
135 | case ENOENT: | ||
136 | case ENOTDIR: | ||
137 | case EBADF: | ||
138 | case ELOOP: | ||
139 | ret = SSH_FX_NO_SUCH_FILE; | ||
140 | break; | ||
141 | case EPERM: | ||
142 | case EACCES: | ||
143 | case EFAULT: | ||
144 | ret = SSH_FX_PERMISSION_DENIED; | ||
145 | break; | ||
146 | case ENAMETOOLONG: | ||
147 | case EINVAL: | ||
148 | ret = SSH_FX_BAD_MESSAGE; | ||
149 | break; | ||
150 | default: | ||
151 | ret = SSH_FX_FAILURE; | ||
152 | break; | ||
153 | } | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | int | ||
158 | flags_from_portable(int pflags) | ||
159 | { | ||
160 | int flags = 0; | ||
161 | if (pflags & SSH_FXF_READ && | ||
162 | pflags & SSH_FXF_WRITE) { | ||
163 | flags = O_RDWR; | ||
164 | } else if (pflags & SSH_FXF_READ) { | ||
165 | flags = O_RDONLY; | ||
166 | } else if (pflags & SSH_FXF_WRITE) { | ||
167 | flags = O_WRONLY; | ||
168 | } | ||
169 | if (pflags & SSH_FXF_CREAT) | ||
170 | flags |= O_CREAT; | ||
171 | if (pflags & SSH_FXF_TRUNC) | ||
172 | flags |= O_TRUNC; | ||
173 | if (pflags & SSH_FXF_EXCL) | ||
174 | flags |= O_EXCL; | ||
175 | return flags; | ||
176 | } | ||
177 | |||
178 | void | ||
179 | attrib_clear(Attrib *a) | ||
180 | { | ||
181 | a->flags = 0; | ||
182 | a->size_low = 0; | ||
183 | a->size_high = 0; | ||
184 | a->size = 0; | ||
185 | a->uid = 0; | ||
186 | a->gid = 0; | ||
187 | a->perm = 0; | ||
188 | a->atime = 0; | ||
189 | a->mtime = 0; | ||
190 | } | ||
191 | |||
192 | Attrib * | ||
193 | decode_attrib(Buffer *b) | ||
194 | { | ||
195 | static Attrib a; | ||
196 | attrib_clear(&a); | ||
197 | a.flags = get_int(); | ||
198 | if (a.flags & SSH_FXA_HAVE_SIZE) { | ||
199 | a.size_high = get_int(); | ||
200 | a.size_low = get_int(); | ||
201 | a.size = (((u_int64_t) a.size_high) << 32) + a.size_low; | ||
202 | } | ||
203 | if (a.flags & SSH_FXA_HAVE_UGID) { | ||
204 | a.uid = get_int(); | ||
205 | a.gid = get_int(); | ||
206 | } | ||
207 | if (a.flags & SSH_FXA_HAVE_PERM) { | ||
208 | a.perm = get_int(); | ||
209 | } | ||
210 | if (a.flags & SSH_FXA_HAVE_TIME) { | ||
211 | a.atime = get_int(); | ||
212 | a.mtime = get_int(); | ||
213 | } | ||
214 | return &a; | ||
215 | } | ||
216 | |||
217 | void | ||
218 | encode_attrib(Buffer *b, Attrib *a) | ||
219 | { | ||
220 | buffer_put_int(b, a->flags); | ||
221 | if (a->flags & SSH_FXA_HAVE_SIZE) { | ||
222 | buffer_put_int(b, a->size_high); | ||
223 | buffer_put_int(b, a->size_low); | ||
224 | } | ||
225 | if (a->flags & SSH_FXA_HAVE_UGID) { | ||
226 | buffer_put_int(b, a->uid); | ||
227 | buffer_put_int(b, a->gid); | ||
228 | } | ||
229 | if (a->flags & SSH_FXA_HAVE_PERM) { | ||
230 | buffer_put_int(b, a->perm); | ||
231 | } | ||
232 | if (a->flags & SSH_FXA_HAVE_TIME) { | ||
233 | buffer_put_int(b, a->atime); | ||
234 | buffer_put_int(b, a->mtime); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | Attrib * | ||
239 | stat_to_attrib(struct stat *st) | ||
240 | { | ||
241 | static Attrib a; | ||
242 | attrib_clear(&a); | ||
243 | a.flags = 0; | ||
244 | a.flags |= SSH_FXA_HAVE_SIZE; | ||
245 | a.size = st->st_size; | ||
246 | a.size_low = a.size; | ||
247 | a.size_high = (u_int32_t) (a.size >> 32); | ||
248 | a.flags |= SSH_FXA_HAVE_UGID; | ||
249 | a.uid = st->st_uid; | ||
250 | a.gid = st->st_gid; | ||
251 | a.flags |= SSH_FXA_HAVE_PERM; | ||
252 | a.perm = st->st_mode; | ||
253 | a.flags |= SSH_FXA_HAVE_TIME; | ||
254 | a.atime = st->st_atime; | ||
255 | a.mtime = st->st_mtime; | ||
256 | return &a; | ||
257 | } | ||
258 | |||
259 | Attrib * | ||
260 | get_attrib(void) | ||
261 | { | ||
262 | return decode_attrib(&iqueue); | ||
263 | } | ||
264 | |||
265 | /* handle handles */ | ||
266 | |||
267 | typedef struct Handle Handle; | ||
268 | struct Handle { | ||
269 | int use; | ||
270 | DIR *dirp; | ||
271 | int fd; | ||
272 | char *name; | ||
273 | }; | ||
274 | enum { | ||
275 | HANDLE_UNUSED, | ||
276 | HANDLE_DIR, | ||
277 | HANDLE_FILE | ||
278 | }; | ||
279 | Handle handles[100]; | ||
280 | |||
281 | void | ||
282 | handle_init(void) | ||
283 | { | ||
284 | int i; | ||
285 | for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) | ||
286 | handles[i].use = HANDLE_UNUSED; | ||
287 | } | ||
288 | |||
289 | int | ||
290 | handle_new(int use, char *name, int fd, DIR *dirp) | ||
291 | { | ||
292 | int i; | ||
293 | for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) { | ||
294 | if (handles[i].use == HANDLE_UNUSED) { | ||
295 | handles[i].use = use; | ||
296 | handles[i].dirp = dirp; | ||
297 | handles[i].fd = fd; | ||
298 | handles[i].name = name; | ||
299 | return i; | ||
300 | } | ||
301 | } | ||
302 | return -1; | ||
303 | } | ||
304 | |||
305 | int | ||
306 | handle_is_ok(int i, int type) | ||
307 | { | ||
308 | return i >= 0 && i < sizeof(handles)/sizeof(Handle) && handles[i].use == type; | ||
309 | } | ||
310 | |||
311 | int | ||
312 | handle_to_string(int handle, char **stringp, int *hlenp) | ||
313 | { | ||
314 | char buf[1024]; | ||
315 | if (stringp == NULL || hlenp == NULL) | ||
316 | return -1; | ||
317 | snprintf(buf, sizeof buf, "%d", handle); | ||
318 | *stringp = xstrdup(buf); | ||
319 | *hlenp = strlen(*stringp); | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | int | ||
324 | handle_from_string(char *handle, int hlen) | ||
325 | { | ||
326 | /* XXX OVERFLOW ? */ | ||
327 | char *ep; | ||
328 | long lval = strtol(handle, &ep, 10); | ||
329 | int val = lval; | ||
330 | if (*ep != '\0') | ||
331 | return -1; | ||
332 | if (handle_is_ok(val, HANDLE_FILE) || | ||
333 | handle_is_ok(val, HANDLE_DIR)) | ||
334 | return val; | ||
335 | return -1; | ||
336 | } | ||
337 | |||
338 | char * | ||
339 | handle_to_name(int handle) | ||
340 | { | ||
341 | if (handle_is_ok(handle, HANDLE_DIR)|| | ||
342 | handle_is_ok(handle, HANDLE_FILE)) | ||
343 | return handles[handle].name; | ||
344 | return NULL; | ||
345 | } | ||
346 | |||
347 | DIR * | ||
348 | handle_to_dir(int handle) | ||
349 | { | ||
350 | if (handle_is_ok(handle, HANDLE_DIR)) | ||
351 | return handles[handle].dirp; | ||
352 | return NULL; | ||
353 | } | ||
354 | |||
355 | int | ||
356 | handle_to_fd(int handle) | ||
357 | { | ||
358 | if (handle_is_ok(handle, HANDLE_FILE)) | ||
359 | return handles[handle].fd; | ||
360 | return -1; | ||
361 | } | ||
362 | |||
363 | int | ||
364 | handle_close(int handle) | ||
365 | { | ||
366 | int ret = -1; | ||
367 | if (handle_is_ok(handle, HANDLE_FILE)) { | ||
368 | ret = close(handles[handle].fd); | ||
369 | handles[handle].use = HANDLE_UNUSED; | ||
370 | } else if (handle_is_ok(handle, HANDLE_DIR)) { | ||
371 | ret = closedir(handles[handle].dirp); | ||
372 | handles[handle].use = HANDLE_UNUSED; | ||
373 | } else { | ||
374 | errno = ENOENT; | ||
375 | } | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | int | ||
380 | get_handle(void) | ||
381 | { | ||
382 | char *handle; | ||
383 | int hlen, val; | ||
384 | handle = get_string(&hlen); | ||
385 | val = handle_from_string(handle, hlen); | ||
386 | xfree(handle); | ||
387 | return val; | ||
388 | } | ||
389 | |||
390 | /* send replies */ | ||
391 | |||
392 | void | ||
393 | send_msg(Buffer *m) | ||
394 | { | ||
395 | int mlen = buffer_len(m); | ||
396 | buffer_put_int(&oqueue, mlen); | ||
397 | buffer_append(&oqueue, buffer_ptr(m), mlen); | ||
398 | buffer_consume(m, mlen); | ||
399 | } | ||
400 | |||
401 | void | ||
402 | send_status(u_int32_t id, u_int32_t error) | ||
403 | { | ||
404 | Buffer msg; | ||
405 | TRACE("sent status id %d error %d", id, error); | ||
406 | buffer_init(&msg); | ||
407 | buffer_put_char(&msg, SSH_FXP_STATUS); | ||
408 | buffer_put_int(&msg, id); | ||
409 | buffer_put_int(&msg, error); | ||
410 | send_msg(&msg); | ||
411 | buffer_free(&msg); | ||
412 | } | ||
413 | void | ||
414 | send_data_or_handle(char type, u_int32_t id, char *data, int dlen) | ||
415 | { | ||
416 | Buffer msg; | ||
417 | buffer_init(&msg); | ||
418 | buffer_put_char(&msg, type); | ||
419 | buffer_put_int(&msg, id); | ||
420 | buffer_put_string(&msg, data, dlen); | ||
421 | send_msg(&msg); | ||
422 | buffer_free(&msg); | ||
423 | } | ||
424 | |||
425 | void | ||
426 | send_data(u_int32_t id, char *data, int dlen) | ||
427 | { | ||
428 | TRACE("sent data id %d len %d", id, dlen); | ||
429 | send_data_or_handle(SSH_FXP_DATA, id, data, dlen); | ||
430 | } | ||
431 | |||
432 | void | ||
433 | send_handle(u_int32_t id, int handle) | ||
434 | { | ||
435 | char *string; | ||
436 | int hlen; | ||
437 | handle_to_string(handle, &string, &hlen); | ||
438 | TRACE("sent handle id %d handle %d", id, handle); | ||
439 | send_data_or_handle(SSH_FXP_HANDLE, id, string, hlen); | ||
440 | xfree(string); | ||
441 | } | ||
442 | |||
443 | void | ||
444 | send_names(u_int32_t id, int count, Stat *stats) | ||
445 | { | ||
446 | Buffer msg; | ||
447 | int i; | ||
448 | buffer_init(&msg); | ||
449 | buffer_put_char(&msg, SSH_FXP_NAME); | ||
450 | buffer_put_int(&msg, id); | ||
451 | buffer_put_int(&msg, count); | ||
452 | TRACE("sent names id %d count %d", id, count); | ||
453 | for (i = 0; i < count; i++) { | ||
454 | buffer_put_cstring(&msg, stats[i].name); | ||
455 | buffer_put_cstring(&msg, stats[i].long_name); | ||
456 | encode_attrib(&msg, &stats[i].attrib); | ||
457 | } | ||
458 | send_msg(&msg); | ||
459 | buffer_free(&msg); | ||
460 | } | ||
461 | |||
462 | void | ||
463 | send_attrib(u_int32_t id, Attrib *a) | ||
464 | { | ||
465 | Buffer msg; | ||
466 | TRACE("sent attrib id %d have 0x%x", id, a->flags); | ||
467 | buffer_init(&msg); | ||
468 | buffer_put_char(&msg, SSH_FXP_ATTRS); | ||
469 | buffer_put_int(&msg, id); | ||
470 | encode_attrib(&msg, a); | ||
471 | send_msg(&msg); | ||
472 | buffer_free(&msg); | ||
473 | } | ||
474 | |||
475 | /* parse incoming */ | ||
476 | |||
477 | void | ||
478 | process_init(void) | ||
479 | { | ||
480 | Buffer msg; | ||
481 | int version = buffer_get_int(&iqueue); | ||
482 | |||
483 | TRACE("client version %d", version); | ||
484 | buffer_init(&msg); | ||
485 | buffer_put_char(&msg, SSH_FXP_VERSION); | ||
486 | buffer_put_int(&msg, SSH_FILEXFER_VERSION); | ||
487 | send_msg(&msg); | ||
488 | buffer_free(&msg); | ||
489 | } | ||
490 | |||
491 | void | ||
492 | process_open(void) | ||
493 | { | ||
494 | u_int32_t id, pflags; | ||
495 | Attrib *a; | ||
496 | char *name; | ||
497 | int handle, fd, flags, mode, status = SSH_FX_FAILURE; | ||
498 | |||
499 | id = get_int(); | ||
500 | name = get_string(NULL); | ||
501 | pflags = get_int(); | ||
502 | a = get_attrib(); | ||
503 | flags = flags_from_portable(pflags); | ||
504 | mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm : 0666; | ||
505 | TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode); | ||
506 | fd = open(name, flags, mode); | ||
507 | if (fd < 0) { | ||
508 | status = errno_to_portable(errno); | ||
509 | } else { | ||
510 | handle = handle_new(HANDLE_FILE, xstrdup(name), fd, NULL); | ||
511 | if (handle < 0) { | ||
512 | close(fd); | ||
513 | } else { | ||
514 | send_handle(id, handle); | ||
515 | status = SSH_FX_OK; | ||
516 | } | ||
517 | } | ||
518 | if (status != SSH_FX_OK) | ||
519 | send_status(id, status); | ||
520 | xfree(name); | ||
521 | } | ||
522 | |||
523 | void | ||
524 | process_close(void) | ||
525 | { | ||
526 | u_int32_t id; | ||
527 | int handle, ret, status = SSH_FX_FAILURE; | ||
528 | |||
529 | id = get_int(); | ||
530 | handle = get_handle(); | ||
531 | TRACE("close id %d handle %d", id, handle); | ||
532 | ret = handle_close(handle); | ||
533 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | ||
534 | send_status(id, status); | ||
535 | } | ||
536 | |||
537 | void | ||
538 | process_read(void) | ||
539 | { | ||
540 | char buf[64*1024]; | ||
541 | u_int32_t id, off_high, off_low, len; | ||
542 | int handle, fd, ret, status = SSH_FX_FAILURE; | ||
543 | u_int64_t off; | ||
544 | |||
545 | id = get_int(); | ||
546 | handle = get_handle(); | ||
547 | off_high = get_int(); | ||
548 | off_low = get_int(); | ||
549 | len = get_int(); | ||
550 | |||
551 | off = (((u_int64_t) off_high) << 32) + off_low; | ||
552 | TRACE("read id %d handle %d off %qd len %d", id, handle, off, len); | ||
553 | if (len > sizeof buf) { | ||
554 | len = sizeof buf; | ||
555 | log("read change len %d", len); | ||
556 | } | ||
557 | fd = handle_to_fd(handle); | ||
558 | if (fd >= 0) { | ||
559 | if (lseek(fd, off, SEEK_SET) < 0) { | ||
560 | error("process_read: seek failed"); | ||
561 | status = errno_to_portable(errno); | ||
562 | } else { | ||
563 | ret = read(fd, buf, len); | ||
564 | if (ret < 0) { | ||
565 | status = errno_to_portable(errno); | ||
566 | } else if (ret == 0) { | ||
567 | status = SSH_FX_EOF; | ||
568 | } else { | ||
569 | send_data(id, buf, ret); | ||
570 | status = SSH_FX_OK; | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | if (status != SSH_FX_OK) | ||
575 | send_status(id, status); | ||
576 | } | ||
577 | |||
578 | void | ||
579 | process_write(void) | ||
580 | { | ||
581 | u_int32_t id, off_high, off_low; | ||
582 | u_int64_t off; | ||
583 | int len; | ||
584 | int handle, fd, ret, status = SSH_FX_FAILURE; | ||
585 | char *data; | ||
586 | |||
587 | id = get_int(); | ||
588 | handle = get_handle(); | ||
589 | off_high = get_int(); | ||
590 | off_low = get_int(); | ||
591 | data = get_string(&len); | ||
592 | |||
593 | off = (((u_int64_t) off_high) << 32) + off_low; | ||
594 | TRACE("write id %d handle %d off %qd len %d", id, handle, off, len); | ||
595 | fd = handle_to_fd(handle); | ||
596 | if (fd >= 0) { | ||
597 | if (lseek(fd, off, SEEK_SET) < 0) { | ||
598 | status = errno_to_portable(errno); | ||
599 | error("process_write: seek failed"); | ||
600 | } else { | ||
601 | /* XXX ATOMICIO ? */ | ||
602 | ret = write(fd, data, len); | ||
603 | if (ret == -1) { | ||
604 | error("process_write: write failed"); | ||
605 | status = errno_to_portable(errno); | ||
606 | } else if (ret == len) { | ||
607 | status = SSH_FX_OK; | ||
608 | } else { | ||
609 | log("nothing at all written"); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | send_status(id, status); | ||
614 | xfree(data); | ||
615 | } | ||
616 | |||
617 | void | ||
618 | process_do_stat(int do_lstat) | ||
619 | { | ||
620 | Attrib *a; | ||
621 | struct stat st; | ||
622 | u_int32_t id; | ||
623 | char *name; | ||
624 | int ret, status = SSH_FX_FAILURE; | ||
625 | |||
626 | id = get_int(); | ||
627 | name = get_string(NULL); | ||
628 | TRACE("%sstat id %d name %s", do_lstat ? "l" : "", id, name); | ||
629 | ret = do_lstat ? lstat(name, &st) : stat(name, &st); | ||
630 | if (ret < 0) { | ||
631 | status = errno_to_portable(errno); | ||
632 | } else { | ||
633 | a = stat_to_attrib(&st); | ||
634 | send_attrib(id, a); | ||
635 | status = SSH_FX_OK; | ||
636 | } | ||
637 | if (status != SSH_FX_OK) | ||
638 | send_status(id, status); | ||
639 | xfree(name); | ||
640 | } | ||
641 | |||
642 | void | ||
643 | process_stat(void) | ||
644 | { | ||
645 | process_do_stat(0); | ||
646 | } | ||
647 | |||
648 | void | ||
649 | process_lstat(void) | ||
650 | { | ||
651 | process_do_stat(1); | ||
652 | } | ||
653 | |||
654 | void | ||
655 | process_fstat(void) | ||
656 | { | ||
657 | Attrib *a; | ||
658 | struct stat st; | ||
659 | u_int32_t id; | ||
660 | int fd, ret, handle, status = SSH_FX_FAILURE; | ||
661 | |||
662 | id = get_int(); | ||
663 | handle = get_handle(); | ||
664 | TRACE("fstat id %d handle %d", id, handle); | ||
665 | fd = handle_to_fd(handle); | ||
666 | if (fd >= 0) { | ||
667 | ret = fstat(fd, &st); | ||
668 | if (ret < 0) { | ||
669 | status = errno_to_portable(errno); | ||
670 | } else { | ||
671 | a = stat_to_attrib(&st); | ||
672 | send_attrib(id, a); | ||
673 | status = SSH_FX_OK; | ||
674 | } | ||
675 | } | ||
676 | if (status != SSH_FX_OK) | ||
677 | send_status(id, status); | ||
678 | } | ||
679 | |||
680 | struct timeval * | ||
681 | attrib_to_tv(Attrib *a) | ||
682 | { | ||
683 | static struct timeval tv[2]; | ||
684 | tv[0].tv_sec = a->atime; | ||
685 | tv[0].tv_usec = 0; | ||
686 | tv[1].tv_sec = a->mtime; | ||
687 | tv[1].tv_usec = 0; | ||
688 | return tv; | ||
689 | } | ||
690 | |||
691 | void | ||
692 | process_setstat(void) | ||
693 | { | ||
694 | Attrib *a; | ||
695 | u_int32_t id; | ||
696 | char *name; | ||
697 | int ret; | ||
698 | int status = SSH_FX_OK; | ||
699 | |||
700 | id = get_int(); | ||
701 | name = get_string(NULL); | ||
702 | a = get_attrib(); | ||
703 | TRACE("setstat id %d name %s", id, name); | ||
704 | if (a->flags & SSH_FXA_HAVE_PERM) { | ||
705 | ret = chmod(name, a->perm & 0777); | ||
706 | if (ret == -1) | ||
707 | status = errno_to_portable(errno); | ||
708 | } | ||
709 | if (a->flags & SSH_FXA_HAVE_TIME) { | ||
710 | ret = utimes(name, attrib_to_tv(a)); | ||
711 | if (ret == -1) | ||
712 | status = errno_to_portable(errno); | ||
713 | } | ||
714 | send_status(id, status); | ||
715 | xfree(name); | ||
716 | } | ||
717 | |||
718 | void | ||
719 | process_fsetstat(void) | ||
720 | { | ||
721 | Attrib *a; | ||
722 | u_int32_t id; | ||
723 | int handle, fd, ret; | ||
724 | int status = SSH_FX_OK; | ||
725 | char *name = NULL; | ||
726 | |||
727 | id = get_int(); | ||
728 | handle = get_handle(); | ||
729 | a = get_attrib(); | ||
730 | TRACE("fsetstat id %d handle %d", id, handle); | ||
731 | fd = handle_to_fd(handle); | ||
732 | name = handle_to_name(handle); | ||
733 | if ((fd < 0) || (name == NULL)) { | ||
734 | status = SSH_FX_FAILURE; | ||
735 | } else { | ||
736 | if (a->flags & SSH_FXA_HAVE_PERM) { | ||
737 | ret = fchmod(fd, a->perm & 0777); | ||
738 | if (ret == -1) | ||
739 | status = errno_to_portable(errno); | ||
740 | } | ||
741 | if (a->flags & SSH_FXA_HAVE_TIME) { | ||
742 | #ifdef HAVE_FUTIMES | ||
743 | ret = futimes(fd, attrib_to_tv(a)); | ||
744 | #else | ||
745 | ret = utimes(name, attrib_to_tv(a)); | ||
746 | #endif | ||
747 | if (ret == -1) | ||
748 | status = errno_to_portable(errno); | ||
749 | } | ||
750 | } | ||
751 | send_status(id, status); | ||
752 | } | ||
753 | |||
754 | void | ||
755 | process_opendir(void) | ||
756 | { | ||
757 | DIR *dirp = NULL; | ||
758 | char *path; | ||
759 | int handle, status = SSH_FX_FAILURE; | ||
760 | u_int32_t id; | ||
761 | |||
762 | id = get_int(); | ||
763 | path = get_string(NULL); | ||
764 | TRACE("opendir id %d path %s", id, path); | ||
765 | dirp = opendir(path); | ||
766 | if (dirp == NULL) { | ||
767 | status = errno_to_portable(errno); | ||
768 | } else { | ||
769 | handle = handle_new(HANDLE_DIR, xstrdup(path), 0, dirp); | ||
770 | if (handle < 0) { | ||
771 | closedir(dirp); | ||
772 | } else { | ||
773 | send_handle(id, handle); | ||
774 | status = SSH_FX_OK; | ||
775 | } | ||
776 | |||
777 | } | ||
778 | if (status != SSH_FX_OK) | ||
779 | send_status(id, status); | ||
780 | xfree(path); | ||
781 | } | ||
782 | |||
783 | char * | ||
784 | ls_file(char *name, struct stat *st) | ||
785 | { | ||
786 | char buf[1024]; | ||
787 | snprintf(buf, sizeof buf, "0%o %d %d %qd %d %s", | ||
788 | st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size,(int) st->st_mtime, | ||
789 | name); | ||
790 | return xstrdup(buf); | ||
791 | } | ||
792 | |||
793 | void | ||
794 | process_readdir(void) | ||
795 | { | ||
796 | DIR *dirp; | ||
797 | struct dirent *dp; | ||
798 | char *path; | ||
799 | int handle; | ||
800 | u_int32_t id; | ||
801 | |||
802 | id = get_int(); | ||
803 | handle = get_handle(); | ||
804 | TRACE("readdir id %d handle %d", id, handle); | ||
805 | dirp = handle_to_dir(handle); | ||
806 | path = handle_to_name(handle); | ||
807 | if (dirp == NULL || path == NULL) { | ||
808 | send_status(id, SSH_FX_FAILURE); | ||
809 | } else { | ||
810 | Attrib *a; | ||
811 | struct stat st; | ||
812 | char pathname[1024]; | ||
813 | Stat *stats; | ||
814 | int nstats = 10, count = 0, i; | ||
815 | stats = xmalloc(nstats * sizeof(Stat)); | ||
816 | while ((dp = readdir(dirp)) != NULL) { | ||
817 | if (count >= nstats) { | ||
818 | nstats *= 2; | ||
819 | stats = xrealloc(stats, nstats * sizeof(Stat)); | ||
820 | } | ||
821 | /* XXX OVERFLOW ? */ | ||
822 | snprintf(pathname, sizeof pathname, | ||
823 | "%s/%s", path, dp->d_name); | ||
824 | if (lstat(pathname, &st) < 0) | ||
825 | continue; | ||
826 | a = stat_to_attrib(&st); | ||
827 | stats[count].attrib = *a; | ||
828 | stats[count].name = xstrdup(dp->d_name); | ||
829 | stats[count].long_name = ls_file(dp->d_name, &st); | ||
830 | count++; | ||
831 | /* send up to 100 entries in one message */ | ||
832 | if (count == 100) | ||
833 | break; | ||
834 | } | ||
835 | send_names(id, count, stats); | ||
836 | for(i = 0; i < count; i++) { | ||
837 | xfree(stats[i].name); | ||
838 | xfree(stats[i].long_name); | ||
839 | } | ||
840 | xfree(stats); | ||
841 | } | ||
842 | } | ||
843 | |||
844 | void | ||
845 | process_remove(void) | ||
846 | { | ||
847 | char *name; | ||
848 | u_int32_t id; | ||
849 | int status = SSH_FX_FAILURE; | ||
850 | int ret; | ||
851 | |||
852 | id = get_int(); | ||
853 | name = get_string(NULL); | ||
854 | TRACE("remove id %d name %s", id, name); | ||
855 | ret = remove(name); | ||
856 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | ||
857 | send_status(id, status); | ||
858 | xfree(name); | ||
859 | } | ||
860 | |||
861 | void | ||
862 | process_mkdir(void) | ||
863 | { | ||
864 | Attrib *a; | ||
865 | u_int32_t id; | ||
866 | char *name; | ||
867 | int ret, mode, status = SSH_FX_FAILURE; | ||
868 | |||
869 | id = get_int(); | ||
870 | name = get_string(NULL); | ||
871 | a = get_attrib(); | ||
872 | mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm & 0777 : 0777; | ||
873 | TRACE("mkdir id %d name %s mode 0%o", id, name, mode); | ||
874 | ret = mkdir(name, mode); | ||
875 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | ||
876 | send_status(id, status); | ||
877 | xfree(name); | ||
878 | } | ||
879 | |||
880 | void | ||
881 | process_rmdir(void) | ||
882 | { | ||
883 | u_int32_t id; | ||
884 | char *name; | ||
885 | int ret, status; | ||
886 | |||
887 | id = get_int(); | ||
888 | name = get_string(NULL); | ||
889 | TRACE("rmdir id %d name %s", id, name); | ||
890 | ret = rmdir(name); | ||
891 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | ||
892 | send_status(id, status); | ||
893 | xfree(name); | ||
894 | } | ||
895 | |||
896 | void | ||
897 | process_realpath(void) | ||
898 | { | ||
899 | char resolvedname[MAXPATHLEN]; | ||
900 | u_int32_t id; | ||
901 | char *path; | ||
902 | |||
903 | id = get_int(); | ||
904 | path = get_string(NULL); | ||
905 | TRACE("realpath id %d path %s", id, path); | ||
906 | if (realpath(path, resolvedname) == NULL) { | ||
907 | send_status(id, errno_to_portable(errno)); | ||
908 | } else { | ||
909 | Stat s; | ||
910 | attrib_clear(&s.attrib); | ||
911 | s.name = s.long_name = resolvedname; | ||
912 | send_names(id, 1, &s); | ||
913 | } | ||
914 | xfree(path); | ||
915 | } | ||
916 | |||
917 | void | ||
918 | process_rename(void) | ||
919 | { | ||
920 | u_int32_t id; | ||
921 | char *oldpath, *newpath; | ||
922 | int ret, status; | ||
923 | |||
924 | id = get_int(); | ||
925 | oldpath = get_string(NULL); | ||
926 | newpath = get_string(NULL); | ||
927 | TRACE("rename id %d old %s new %s", id, oldpath, newpath); | ||
928 | ret = rename(oldpath, newpath); | ||
929 | status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; | ||
930 | send_status(id, status); | ||
931 | xfree(oldpath); | ||
932 | xfree(newpath); | ||
933 | } | ||
934 | |||
935 | |||
936 | /* stolen from ssh-agent */ | ||
937 | |||
938 | void | ||
939 | process(void) | ||
940 | { | ||
941 | unsigned int msg_len; | ||
942 | unsigned int type; | ||
943 | unsigned char *cp; | ||
944 | |||
945 | if (buffer_len(&iqueue) < 5) | ||
946 | return; /* Incomplete message. */ | ||
947 | cp = (unsigned char *) buffer_ptr(&iqueue); | ||
948 | msg_len = GET_32BIT(cp); | ||
949 | if (msg_len > 256 * 1024) { | ||
950 | error("bad message "); | ||
951 | exit(11); | ||
952 | } | ||
953 | if (buffer_len(&iqueue) < msg_len + 4) | ||
954 | return; | ||
955 | buffer_consume(&iqueue, 4); | ||
956 | type = buffer_get_char(&iqueue); | ||
957 | switch (type) { | ||
958 | case SSH_FXP_INIT: | ||
959 | process_init(); | ||
960 | break; | ||
961 | case SSH_FXP_OPEN: | ||
962 | process_open(); | ||
963 | break; | ||
964 | case SSH_FXP_CLOSE: | ||
965 | process_close(); | ||
966 | break; | ||
967 | case SSH_FXP_READ: | ||
968 | process_read(); | ||
969 | break; | ||
970 | case SSH_FXP_WRITE: | ||
971 | process_write(); | ||
972 | break; | ||
973 | case SSH_FXP_LSTAT: | ||
974 | process_lstat(); | ||
975 | break; | ||
976 | case SSH_FXP_FSTAT: | ||
977 | process_fstat(); | ||
978 | break; | ||
979 | case SSH_FXP_SETSTAT: | ||
980 | process_setstat(); | ||
981 | break; | ||
982 | case SSH_FXP_FSETSTAT: | ||
983 | process_fsetstat(); | ||
984 | break; | ||
985 | case SSH_FXP_OPENDIR: | ||
986 | process_opendir(); | ||
987 | break; | ||
988 | case SSH_FXP_READDIR: | ||
989 | process_readdir(); | ||
990 | break; | ||
991 | case SSH_FXP_REMOVE: | ||
992 | process_remove(); | ||
993 | break; | ||
994 | case SSH_FXP_MKDIR: | ||
995 | process_mkdir(); | ||
996 | break; | ||
997 | case SSH_FXP_RMDIR: | ||
998 | process_rmdir(); | ||
999 | break; | ||
1000 | case SSH_FXP_REALPATH: | ||
1001 | process_realpath(); | ||
1002 | break; | ||
1003 | case SSH_FXP_STAT: | ||
1004 | process_stat(); | ||
1005 | break; | ||
1006 | case SSH_FXP_RENAME: | ||
1007 | process_rename(); | ||
1008 | break; | ||
1009 | default: | ||
1010 | error("Unknown message %d", type); | ||
1011 | break; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | int | ||
1016 | main(int ac, char **av) | ||
1017 | { | ||
1018 | fd_set rset, wset; | ||
1019 | int in, out, max; | ||
1020 | size_t len, olen; | ||
1021 | |||
1022 | handle_init(); | ||
1023 | |||
1024 | in = dup(STDIN_FILENO); | ||
1025 | out = dup(STDOUT_FILENO); | ||
1026 | |||
1027 | max = 0; | ||
1028 | if (in > max) | ||
1029 | max = in; | ||
1030 | if (out > max) | ||
1031 | max = out; | ||
1032 | |||
1033 | buffer_init(&iqueue); | ||
1034 | buffer_init(&oqueue); | ||
1035 | |||
1036 | for (;;) { | ||
1037 | FD_ZERO(&rset); | ||
1038 | FD_ZERO(&wset); | ||
1039 | |||
1040 | FD_SET(in, &rset); | ||
1041 | olen = buffer_len(&oqueue); | ||
1042 | if (olen > 0) | ||
1043 | FD_SET(out, &wset); | ||
1044 | |||
1045 | if (select(max+1, &rset, &wset, NULL, NULL) < 0) { | ||
1046 | if (errno == EINTR) | ||
1047 | continue; | ||
1048 | exit(2); | ||
1049 | } | ||
1050 | |||
1051 | /* copy stdin to iqueue */ | ||
1052 | if (FD_ISSET(in, &rset)) { | ||
1053 | char buf[4*4096]; | ||
1054 | len = read(in, buf, sizeof buf); | ||
1055 | if (len == 0) { | ||
1056 | debug("read eof"); | ||
1057 | exit(0); | ||
1058 | } else if (len < 0) { | ||
1059 | error("read error"); | ||
1060 | exit(1); | ||
1061 | } else { | ||
1062 | buffer_append(&iqueue, buf, len); | ||
1063 | } | ||
1064 | } | ||
1065 | /* send oqueue to stdout */ | ||
1066 | if (FD_ISSET(out, &wset)) { | ||
1067 | len = write(out, buffer_ptr(&oqueue), olen); | ||
1068 | if (len < 0) { | ||
1069 | error("write error"); | ||
1070 | exit(1); | ||
1071 | } else { | ||
1072 | buffer_consume(&oqueue, len); | ||
1073 | } | ||
1074 | } | ||
1075 | /* process requests from client */ | ||
1076 | process(); | ||
1077 | } | ||
1078 | } | ||
@@ -9,7 +9,7 @@ | |||
9 | .\" | 9 | .\" |
10 | .\" Created: Sat Apr 22 23:55:14 1995 ylo | 10 | .\" Created: Sat Apr 22 23:55:14 1995 ylo |
11 | .\" | 11 | .\" |
12 | .\" $Id: ssh-add.1,v 1.15 2000/08/29 00:33:51 djm Exp $ | 12 | .\" $Id: ssh-add.1,v 1.16 2000/09/05 02:34:54 djm Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd September 25, 1999 | 14 | .Dd September 25, 1999 |
15 | .Dt SSH-ADD 1 | 15 | .Dt SSH-ADD 1 |
@@ -65,7 +65,7 @@ This is the default file added by | |||
65 | when no other files have been specified. | 65 | when no other files have been specified. |
66 | .It Pa $HOME/.ssh/id_dsa | 66 | .It Pa $HOME/.ssh/id_dsa |
67 | Contains the DSA authentication identity of the user. | 67 | Contains the DSA authentication identity of the user. |
68 | .Pp | 68 | .El |
69 | .Sh ENVIRONMENT | 69 | .Sh ENVIRONMENT |
70 | .Bl -tag -width Ds | 70 | .Bl -tag -width Ds |
71 | .It Ev "DISPLAY" and "SSH_ASKPASS" | 71 | .It Ev "DISPLAY" and "SSH_ASKPASS" |
@@ -91,6 +91,7 @@ or related script. | |||
91 | may be necessary to redirect the input from | 91 | may be necessary to redirect the input from |
92 | .Pa /dev/null | 92 | .Pa /dev/null |
93 | to make this work.) | 93 | to make this work.) |
94 | .El | ||
94 | .Sh AUTHOR | 95 | .Sh AUTHOR |
95 | Tatu Ylonen <ylo@cs.hut.fi> | 96 | Tatu Ylonen <ylo@cs.hut.fi> |
96 | .Pp | 97 | .Pp |
diff --git a/ssh-agent.c b/ssh-agent.c index 56b81a78d..0bc4722b2 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.34 2000/08/31 22:09:34 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "includes.h" | 14 | #include "includes.h" |
15 | RCSID("$OpenBSD: ssh-agent.c,v 1.33 2000/08/19 21:34:43 markus Exp $"); | 15 | RCSID("$OpenBSD: ssh-agent.c,v 1.34 2000/08/31 22:09:34 markus Exp $"); |
16 | 16 | ||
17 | #include "ssh.h" | 17 | #include "ssh.h" |
18 | #include "rsa.h" | 18 | #include "rsa.h" |
@@ -219,6 +219,7 @@ process_sign_request2(SocketEntry *e) | |||
219 | 219 | ||
220 | blob = buffer_get_string(&e->input, &blen); | 220 | blob = buffer_get_string(&e->input, &blen); |
221 | data = buffer_get_string(&e->input, &dlen); | 221 | data = buffer_get_string(&e->input, &dlen); |
222 | buffer_get_int(&e->input); /* flags, unused */ | ||
222 | 223 | ||
223 | key = dsa_key_from_blob(blob, blen); | 224 | key = dsa_key_from_blob(blob, blen); |
224 | if (key != NULL) { | 225 | if (key != NULL) { |
@@ -9,7 +9,7 @@ | |||
9 | .\" | 9 | .\" |
10 | .\" Created: Sat Apr 22 21:55:14 1995 ylo | 10 | .\" Created: Sat Apr 22 21:55:14 1995 ylo |
11 | .\" | 11 | .\" |
12 | .\" $Id: ssh.1,v 1.30 2000/08/29 00:33:51 djm Exp $ | 12 | .\" $Id: ssh.1,v 1.31 2000/09/05 02:34:54 djm Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd September 25, 1999 | 14 | .Dd September 25, 1999 |
15 | .Dt SSH 1 | 15 | .Dt SSH 1 |
@@ -946,6 +946,7 @@ Specifies the location of the | |||
946 | program. | 946 | program. |
947 | The default is | 947 | The default is |
948 | .Pa /usr/X11R6/bin/xauth . | 948 | .Pa /usr/X11R6/bin/xauth . |
949 | .El | ||
949 | .Sh ENVIRONMENT | 950 | .Sh ENVIRONMENT |
950 | .Nm | 951 | .Nm |
951 | will normally set the following environment variables: | 952 | will normally set the following environment variables: |
@@ -1189,6 +1190,7 @@ above. | |||
1189 | .It Pa libcrypto.so.X.1 | 1190 | .It Pa libcrypto.so.X.1 |
1190 | A version of this library which includes support for the RSA algorithm | 1191 | A version of this library which includes support for the RSA algorithm |
1191 | is required for proper operation. | 1192 | is required for proper operation. |
1193 | .El | ||
1192 | .Sh AUTHOR | 1194 | .Sh AUTHOR |
1193 | OpenSSH | 1195 | OpenSSH |
1194 | is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, | 1196 | is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, |
@@ -9,7 +9,7 @@ | |||
9 | .\" | 9 | .\" |
10 | .\" Created: Sat Apr 22 21:55:14 1995 ylo | 10 | .\" Created: Sat Apr 22 21:55:14 1995 ylo |
11 | .\" | 11 | .\" |
12 | .\" $Id: sshd.8,v 1.27 2000/08/29 00:33:51 djm Exp $ | 12 | .\" $Id: sshd.8,v 1.28 2000/09/05 02:34:54 djm Exp $ |
13 | .\" | 13 | .\" |
14 | .Dd September 25, 1999 | 14 | .Dd September 25, 1999 |
15 | .Dt SSHD 8 | 15 | .Dt SSHD 8 |
@@ -589,6 +589,11 @@ The default is | |||
589 | .It Cm Subsystem | 589 | .It Cm Subsystem |
590 | Configures an external subsystem (e.g. file transfer daemon). | 590 | Configures an external subsystem (e.g. file transfer daemon). |
591 | Arguments should be a subsystem name and a command to execute upon subsystem request. | 591 | Arguments should be a subsystem name and a command to execute upon subsystem request. |
592 | The command | ||
593 | .Xr sftp-server 8 | ||
594 | implements the | ||
595 | .Dq sftp | ||
596 | file transfer subsystem. | ||
592 | By default no subsystems are defined. | 597 | By default no subsystems are defined. |
593 | Note that this option applies to protocol version 2 only. | 598 | Note that this option applies to protocol version 2 only. |
594 | .It Cm SyslogFacility | 599 | .It Cm SyslogFacility |
@@ -1031,6 +1036,7 @@ Niels Provos, Theo de Raadt, and Dug Song. | |||
1031 | The support for SSH protocol 2 was written by Markus Friedl. | 1036 | The support for SSH protocol 2 was written by Markus Friedl. |
1032 | .Sh SEE ALSO | 1037 | .Sh SEE ALSO |
1033 | .Xr scp 1 , | 1038 | .Xr scp 1 , |
1039 | .Xr sftp-server 8 , | ||
1034 | .Xr ssh 1 , | 1040 | .Xr ssh 1 , |
1035 | .Xr ssh-add 1 , | 1041 | .Xr ssh-add 1 , |
1036 | .Xr ssh-agent 1 , | 1042 | .Xr ssh-agent 1 , |
diff --git a/sshd_config b/sshd_config index b89b19fc8..43d2e8ea6 100644 --- a/sshd_config +++ b/sshd_config | |||
@@ -50,5 +50,6 @@ PermitEmptyPasswords no | |||
50 | CheckMail no | 50 | CheckMail no |
51 | #UseLogin no | 51 | #UseLogin no |
52 | 52 | ||
53 | #Subsystem sftp /usr/local/sbin/sftpd | 53 | # Uncomment if you want to enable sftp |
54 | #Subsystem sftp /usr/libexec/sftp-server | ||
54 | #MaxStartups 10:30:60 | 55 | #MaxStartups 10:30:60 |