- (djm) Sync sftp and scp stuff from OpenBSD:

- djm@cvs.openbsd.org     2001/02/07 03:55:13
     [sftp-client.c]
     Don't free handles before we are done with them. Based on work from
     Corinna Vinschen <vinschen@redhat.com>. ok markus@
   - djm@cvs.openbsd.org     2001/02/06 22:32:53
     [sftp.1]
     Punctuation fix from Pekka Savola <pekkas@netcore.fi>
   - deraadt@cvs.openbsd.org 2001/02/07 04:07:29
     [sftp.1]
     pretty up significantly
   - itojun@cvs.openbsd.org  2001/02/07 06:49:42
     [sftp.1]
     .Bl-.El mismatch.  markus ok
   - djm@cvs.openbsd.org     2001/02/07 06:12:30
     [sftp-int.c]
     Check that target is a directory before doing ls; ok markus@
   - itojun@cvs.openbsd.org  2001/02/07 11:01:18
     [scp.c sftp-client.c sftp-server.c]
     unsigned long long -> %llu, not %qu.  markus ok
   - stevesk@cvs.openbsd.org 2001/02/07 11:10:39
     [sftp.1 sftp-int.c]
     more man page cleanup and sync of help text with man page; ok markus@
   - markus@cvs.openbsd.org  2001/02/07 14:58:34
     [sftp-client.c]
     older servers reply with SSH2_FXP_NAME + count==0 instead of EOF
   - djm@cvs.openbsd.org     2001/02/07 15:27:19
     [sftp.c]
     Don't forward agent and X11 in sftp. Suggestion from Roumen Petrov
     <roumen.petrov@skalasoft.com>
   - stevesk@cvs.openbsd.org 2001/02/07 15:36:04
     [sftp-int.c]
     portable; ok markus@
   - stevesk@cvs.openbsd.org 2001/02/07 15:55:47
     [sftp-int.c]
     lowercase cmds[].c also; ok markus@
   - markus@cvs.openbsd.org  2001/02/07 17:04:52
     [pathnames.h sftp.c]
     allow sftp over ssh protocol 1; ok djm@
   - deraadt@cvs.openbsd.org 2001/02/08 07:38:55
     [scp.c]
     memory leak fix, and snprintf throughout
   - deraadt@cvs.openbsd.org 2001/02/08 08:02:02
     [sftp-int.c]
     plug a memory leak
   - stevesk@cvs.openbsd.org 2001/02/08 10:11:23
     [session.c sftp-client.c]
     %i -> %d
   - stevesk@cvs.openbsd.org 2001/02/08 10:57:59
     [sftp-int.c]
     typo
   - stevesk@cvs.openbsd.org 2001/02/08 15:28:07
     [sftp-int.c pathnames.h]
     _PATH_LS; ok markus@
   - djm@cvs.openbsd.org     2001/02/09 04:46:25
     [sftp-int.c]
     Check for NULL attribs for chown, chmod & chgrp operations, only send
     relevant attribs back to server; ok markus@
 - (djm) Update makefile.in for _PATH_SFTP_SERVER
This commit is contained in:
Damien Miller 2001-02-10 00:40:03 +11:00
parent 4192c46791
commit d7686fd1fb
8 changed files with 364 additions and 201 deletions

View File

@ -1,3 +1,67 @@
20010210
- (djm) Sync sftp and scp stuff from OpenBSD:
- djm@cvs.openbsd.org 2001/02/07 03:55:13
[sftp-client.c]
Don't free handles before we are done with them. Based on work from
Corinna Vinschen <vinschen@redhat.com>. ok markus@
- djm@cvs.openbsd.org 2001/02/06 22:32:53
[sftp.1]
Punctuation fix from Pekka Savola <pekkas@netcore.fi>
- deraadt@cvs.openbsd.org 2001/02/07 04:07:29
[sftp.1]
pretty up significantly
- itojun@cvs.openbsd.org 2001/02/07 06:49:42
[sftp.1]
.Bl-.El mismatch. markus ok
- djm@cvs.openbsd.org 2001/02/07 06:12:30
[sftp-int.c]
Check that target is a directory before doing ls; ok markus@
- itojun@cvs.openbsd.org 2001/02/07 11:01:18
[scp.c sftp-client.c sftp-server.c]
unsigned long long -> %llu, not %qu. markus ok
- stevesk@cvs.openbsd.org 2001/02/07 11:10:39
[sftp.1 sftp-int.c]
more man page cleanup and sync of help text with man page; ok markus@
- markus@cvs.openbsd.org 2001/02/07 14:58:34
[sftp-client.c]
older servers reply with SSH2_FXP_NAME + count==0 instead of EOF
- djm@cvs.openbsd.org 2001/02/07 15:27:19
[sftp.c]
Don't forward agent and X11 in sftp. Suggestion from Roumen Petrov
<roumen.petrov@skalasoft.com>
- stevesk@cvs.openbsd.org 2001/02/07 15:36:04
[sftp-int.c]
portable; ok markus@
- stevesk@cvs.openbsd.org 2001/02/07 15:55:47
[sftp-int.c]
lowercase cmds[].c also; ok markus@
- markus@cvs.openbsd.org 2001/02/07 17:04:52
[pathnames.h sftp.c]
allow sftp over ssh protocol 1; ok djm@
- deraadt@cvs.openbsd.org 2001/02/08 07:38:55
[scp.c]
memory leak fix, and snprintf throughout
- deraadt@cvs.openbsd.org 2001/02/08 08:02:02
[sftp-int.c]
plug a memory leak
- stevesk@cvs.openbsd.org 2001/02/08 10:11:23
[session.c sftp-client.c]
%i -> %d
- stevesk@cvs.openbsd.org 2001/02/08 10:57:59
[sftp-int.c]
typo
- stevesk@cvs.openbsd.org 2001/02/08 15:28:07
[sftp-int.c pathnames.h]
_PATH_LS; ok markus@
- djm@cvs.openbsd.org 2001/02/09 04:46:25
[sftp-int.c]
Check for NULL attribs for chown, chmod & chgrp operations, only send
relevant attribs back to server; ok markus@
- (djm) Update makefile.in for _PATH_SFTP_SERVER
20010209 20010209
- (bal) patch to vis.c to deal with HAVE_VIS right by Robert Mooney - (bal) patch to vis.c to deal with HAVE_VIS right by Robert Mooney
<rjmooney@mediaone.net> <rjmooney@mediaone.net>
@ -3703,4 +3767,4 @@
- Wrote replacements for strlcpy and mkdtemp - Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1 - Released 1.0pre1
$Id: ChangeLog,v 1.709 2001/02/09 11:55:16 djm Exp $ $Id: ChangeLog,v 1.710 2001/02/09 13:40:03 djm Exp $

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.149 2001/02/07 23:07:09 djm Exp $ # $Id: Makefile.in,v 1.150 2001/02/09 13:40:03 djm Exp $
prefix=@prefix@ prefix=@prefix@
exec_prefix=@exec_prefix@ exec_prefix=@exec_prefix@
@ -16,10 +16,15 @@ DESTDIR=
VPATH=@srcdir@ VPATH=@srcdir@
SSH_PROGRAM=@bindir@/ssh SSH_PROGRAM=@bindir@/ssh
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
PATHS= -DETCDIR=\"$(sysconfdir)\" \
-D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\"
CC=@CC@ CC=@CC@
LD=@LD@ LD=@LD@
PATHS=-DETCDIR=\"$(sysconfdir)\" -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\"
CFLAGS=@CFLAGS@ CFLAGS=@CFLAGS@
CPPFLAGS=@CPPFLAGS@ -I. -I$(srcdir)/openbsd-compat -I$(srcdir) $(PATHS) @DEFS@ CPPFLAGS=@CPPFLAGS@ -I. -I$(srcdir)/openbsd-compat -I$(srcdir) $(PATHS) @DEFS@
LIBS=@LIBS@ LIBS=@LIBS@
@ -162,7 +167,7 @@ install-files:
$(INSTALL) -m 0775 -s ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan $(INSTALL) -m 0775 -s ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan
$(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd $(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 $(DESTDIR)$(bindir)/sftp
@NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(libexecdir)/sftp-server @NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(SFTP_SERVER)
$(INSTALL) -m 644 ssh.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 $(INSTALL) -m 644 ssh.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
$(INSTALL) -m 644 scp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 $(INSTALL) -m 644 scp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
$(INSTALL) -m 644 ssh-add.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 $(INSTALL) -m 644 ssh-add.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
@ -250,7 +255,7 @@ uninstall:
-rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
-rm -r $(DESTDIR)$(libexecdir)/sftp-server$(EXEEXT) -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pathnames.h,v 1.2 2001/01/29 01:58:17 niklas Exp $ */ /* $OpenBSD: pathnames.h,v 1.4 2001/02/08 22:28:07 stevesk Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -116,6 +116,12 @@
#define _PATH_CP "cp" #define _PATH_CP "cp"
#endif #endif
/* for sftp */
#ifndef _PATH_SFTP_SERVER
#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server"
#endif
#define _PATH_LS "ls"
/* path to login program */ /* path to login program */
#ifndef LOGIN_PROGRAM #ifndef LOGIN_PROGRAM
# ifdef LOGIN_PROGRAM_FALLBACK # ifdef LOGIN_PROGRAM_FALLBACK

View File

@ -29,7 +29,7 @@
/* XXX: copy between two remote sites */ /* XXX: copy between two remote sites */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sftp-client.c,v 1.4 2001/02/06 23:30:28 djm Exp $"); RCSID("$OpenBSD: sftp-client.c,v 1.8 2001/02/08 17:11:23 stevesk Exp $");
#include "ssh.h" #include "ssh.h"
#include "buffer.h" #include "buffer.h"
@ -338,7 +338,9 @@ do_ls(int fd_in, int fd_out, char *path)
SSH2_FXP_NAME, type); SSH2_FXP_NAME, type);
count = buffer_get_int(&msg); count = buffer_get_int(&msg);
debug3("Received %i SSH2_FXP_NAME responses", count); if (count == 0)
break;
debug3("Received %d SSH2_FXP_NAME responses", count);
for(i = 0; i < count; i++) { for(i = 0; i < count; i++) {
char *filename, *longname; char *filename, *longname;
Attrib *a; Attrib *a;
@ -556,6 +558,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
char *handle; char *handle;
Buffer msg; Buffer msg;
Attrib junk, *a; Attrib junk, *a;
int status;
a = do_stat(fd_in, fd_out, remote_path); a = do_stat(fd_in, fd_out, remote_path);
if (a == NULL) if (a == NULL)
@ -635,7 +638,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
if (id != expected_id) if (id != expected_id)
fatal("ID mismatch (%d != %d)", id, expected_id); fatal("ID mismatch (%d != %d)", id, expected_id);
if (type == SSH2_FXP_STATUS) { if (type == SSH2_FXP_STATUS) {
int status = buffer_get_int(&msg); status = buffer_get_int(&msg);
if (status == SSH2_FX_EOF) if (status == SSH2_FX_EOF)
break; break;
@ -644,10 +647,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
"file \"%s\" : %s", remote_path, "file \"%s\" : %s", remote_path,
fx2txt(status)); fx2txt(status));
do_close(fd_in, fd_out, handle, handle_len); do_close(fd_in, fd_out, handle, handle_len);
xfree(handle); goto done;
close(local_fd);
buffer_free(&msg);
return(status);
} }
} else if (type != SSH2_FXP_DATA) { } else if (type != SSH2_FXP_DATA) {
fatal("Expected SSH2_FXP_DATA(%d) packet, got %d", fatal("Expected SSH2_FXP_DATA(%d) packet, got %d",
@ -659,27 +659,27 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
fatal("Received more data than asked for %d > %d", fatal("Received more data than asked for %d > %d",
len, COPY_SIZE); len, COPY_SIZE);
debug3("In read loop, got %d offset %lld", len, debug3("In read loop, got %d offset %llu", len,
(unsigned long long)offset); (unsigned long long)offset);
if (atomicio(write, local_fd, data, len) != len) { if (atomicio(write, local_fd, data, len) != len) {
error("Couldn't write to \"%s\": %s", local_path, error("Couldn't write to \"%s\": %s", local_path,
strerror(errno)); strerror(errno));
do_close(fd_in, fd_out, handle, handle_len); do_close(fd_in, fd_out, handle, handle_len);
xfree(handle); status = -1;
close(local_fd);
xfree(data); xfree(data);
buffer_free(&msg); goto done;
return(-1);
} }
offset += len; offset += len;
xfree(data); xfree(data);
} }
xfree(handle); status = do_close(fd_in, fd_out, handle, handle_len);
buffer_free(&msg);
close(local_fd);
return(do_close(fd_in, fd_out, handle, handle_len)); done:
close(local_fd);
buffer_free(&msg);
xfree(handle);
return status;
} }
int int
@ -693,6 +693,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
Buffer msg; Buffer msg;
struct stat sb; struct stat sb;
Attrib a; Attrib a;
int status;
if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
error("Couldn't open local file \"%s\" for reading: %s", error("Couldn't open local file \"%s\" for reading: %s",
@ -743,7 +744,6 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
for(;;) { for(;;) {
int len; int len;
char data[COPY_SIZE]; char data[COPY_SIZE];
u_int status;
/* /*
* Can't use atomicio here because it returns 0 on EOF, thus losing * Can't use atomicio here because it returns 0 on EOF, thus losing
@ -774,24 +774,29 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
error("Couldn't write to remote file \"%s\": %s", error("Couldn't write to remote file \"%s\": %s",
remote_path, fx2txt(status)); remote_path, fx2txt(status));
do_close(fd_in, fd_out, handle, handle_len); do_close(fd_in, fd_out, handle, handle_len);
xfree(handle);
close(local_fd); close(local_fd);
return(-1); goto done;
} }
debug3("In write loop, got %d offset %llu", len, debug3("In write loop, got %d offset %llu", len,
(unsigned long long)offset); (unsigned long long)offset);
offset += len; offset += len;
} }
xfree(handle);
buffer_free(&msg);
if (close(local_fd) == -1) { if (close(local_fd) == -1) {
error("Couldn't close local file \"%s\": %s", local_path, error("Couldn't close local file \"%s\": %s", local_path,
strerror(errno)); strerror(errno));
do_close(fd_in, fd_out, handle, handle_len); do_close(fd_in, fd_out, handle, handle_len);
return(-1); status = -1;
goto done;
} }
return(do_close(fd_in, fd_out, handle, handle_len)); status = do_close(fd_in, fd_out, handle, handle_len);
done:
xfree(handle);
buffer_free(&msg);
return status;
} }

View File

@ -24,7 +24,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sftp-common.c,v 1.1 2001/02/04 11:11:54 djm Exp $"); RCSID("$OpenBSD: sftp-common.c,v 1.2 2001/02/06 23:50:10 markus Exp $");
#include "buffer.h" #include "buffer.h"
#include "bufaux.h" #include "bufaux.h"
@ -121,13 +121,13 @@ fx2txt(int status)
{ {
switch (status) { switch (status) {
case SSH2_FX_OK: case SSH2_FX_OK:
return("No Error"); return("No error");
case SSH2_FX_EOF: case SSH2_FX_EOF:
return("End of File"); return("End of file");
case SSH2_FX_NO_SUCH_FILE: case SSH2_FX_NO_SUCH_FILE:
return("No Such File"); return("No such file or directory");
case SSH2_FX_PERMISSION_DENIED: case SSH2_FX_PERMISSION_DENIED:
return("Permission Denied"); return("Permission denied");
case SSH2_FX_FAILURE: case SSH2_FX_FAILURE:
return("Failure"); return("Failure");
case SSH2_FX_BAD_MESSAGE: case SSH2_FX_BAD_MESSAGE:

View File

@ -24,10 +24,11 @@
/* XXX: finish implementation of all commands */ /* XXX: finish implementation of all commands */
/* XXX: do fnmatch() instead of using raw pathname */ /* XXX: do fnmatch() instead of using raw pathname */
/* XXX: globbed ls */
/* XXX: recursive operations */ /* XXX: recursive operations */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sftp-int.c,v 1.7 2001/02/05 00:02:32 deraadt Exp $"); RCSID("$OpenBSD: sftp-int.c,v 1.19 2001/02/09 11:46:24 djm Exp $");
#include "buffer.h" #include "buffer.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -70,28 +71,29 @@ struct CMD {
}; };
const struct CMD cmds[] = { const struct CMD cmds[] = {
{ "CD", I_CHDIR }, { "cd", I_CHDIR },
{ "CHDIR", I_CHDIR }, { "chdir", I_CHDIR },
{ "CHGRP", I_CHGRP }, { "chgrp", I_CHGRP },
{ "CHMOD", I_CHMOD }, { "chmod", I_CHMOD },
{ "CHOWN", I_CHOWN }, { "chown", I_CHOWN },
{ "EXIT", I_QUIT }, { "dir", I_LS },
{ "GET", I_GET }, { "exit", I_QUIT },
{ "HELP", I_HELP }, { "get", I_GET },
{ "LCD", I_LCHDIR }, { "help", I_HELP },
{ "LCHDIR", I_LCHDIR }, { "lcd", I_LCHDIR },
{ "LLS", I_LLS }, { "lchdir", I_LCHDIR },
{ "LMKDIR", I_LMKDIR }, { "lls", I_LLS },
{ "LPWD", I_LPWD }, { "lmkdir", I_LMKDIR },
{ "LS", I_LS }, { "lpwd", I_LPWD },
{ "LUMASK", I_LUMASK }, { "ls", I_LS },
{ "MKDIR", I_MKDIR }, { "lumask", I_LUMASK },
{ "PUT", I_PUT }, { "mkdir", I_MKDIR },
{ "PWD", I_PWD }, { "put", I_PUT },
{ "QUIT", I_QUIT }, { "pwd", I_PWD },
{ "RENAME", I_RENAME }, { "quit", I_QUIT },
{ "RM", I_RM }, { "rename", I_RENAME },
{ "RMDIR", I_RMDIR }, { "rm", I_RM },
{ "rmdir", I_RMDIR },
{ "!", I_SHELL }, { "!", I_SHELL },
{ "?", I_HELP }, { "?", I_HELP },
{ NULL, -1} { NULL, -1}
@ -101,28 +103,29 @@ void
help(void) help(void)
{ {
printf("Available commands:\n"); printf("Available commands:\n");
printf("CD path Change remote directory to 'path'\n"); printf("cd path Change remote directory to 'path'\n");
printf("LCD path Change local 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("chgrp grp path Change group of file 'path' to 'grp'\n");
printf("CHMOD mode path Change permissions of file 'path' to 'mode'\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("chown own path Change owner of file 'path' to 'own'\n");
printf("HELP Display this help text\n"); printf("help Display this help text\n");
printf("GET remote-path [local-path] Download file\n"); printf("get remote-path [local-path] Download file\n");
printf("LLS [ls options] [path] Display local directory listing\n"); printf("lls [ls-options [path]] Display local directory listing\n");
printf("LMKDIR path Create local directory\n"); printf("lmkdir path Create local directory\n");
printf("LPWD Print local working directory\n"); printf("lpwd Print local working directory\n");
printf("LS [path] Display remote directory listing\n"); printf("ls [path] Display remote directory listing\n");
printf("LUMASK umask Set local umask to 'umask'\n"); printf("lumask umask Set local umask to 'umask'\n");
printf("MKDIR path Create remote directory\n"); printf("mkdir path Create remote directory\n");
printf("PUT local-path [remote-path] Upload file\n"); printf("put local-path [remote-path] Upload file\n");
printf("PWD Display remote working directory\n"); printf("pwd Display remote working directory\n");
printf("EXIT Quit sftp\n"); printf("exit Quit sftp\n");
printf("QUIT Quit sftp\n"); printf("quit Quit sftp\n");
printf("RENAME oldpath newpath Rename remote file\n"); printf("rename oldpath newpath Rename remote file\n");
printf("RMDIR path Remove remote directory\n"); printf("rmdir path Remove remote directory\n");
printf("RM path Delete remote file\n"); printf("rm path Delete remote file\n");
printf("!command Execute 'command' in local shell\n"); printf("!command Execute 'command' in local shell\n");
printf("! Escape to local shell\n"); printf("! Escape to local shell\n");
printf("? Synonym for help\n");
} }
void void
@ -166,13 +169,15 @@ void
local_do_ls(const char *args) local_do_ls(const char *args)
{ {
if (!args || !*args) if (!args || !*args)
local_do_shell("ls"); local_do_shell(_PATH_LS);
else { else {
char *buf = xmalloc(8 + strlen(args) + 1); int len = strlen(_PATH_LS " ") + strlen(args) + 1;
char *buf = xmalloc(len);
/* XXX: quoting - rip quoting code from ftp? */ /* XXX: quoting - rip quoting code from ftp? */
sprintf(buf, "/bin/ls %s", args); snprintf(buf, len, _PATH_LS " %s", args);
local_do_shell(buf); local_do_shell(buf);
xfree(buf);
} }
} }
@ -198,7 +203,7 @@ parse_getput_flags(const char **cpp, int *pflag)
/* Check for flags */ /* Check for flags */
if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) { if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
switch (*cp) { switch (cp[1]) {
case 'P': case 'P':
*pflag = 1; *pflag = 1;
break; break;
@ -216,50 +221,49 @@ parse_getput_flags(const char **cpp, int *pflag)
int int
get_pathname(const char **cpp, char **path) get_pathname(const char **cpp, char **path)
{ {
const char *quot, *cp = *cpp; const char *cp = *cpp, *end;
char quot;
int i; int i;
cp += strspn(cp, WHITESPACE); cp += strspn(cp, WHITESPACE);
if (!*cp) { if (!*cp) {
*cpp = cp; *cpp = cp;
*path = NULL; *path = NULL;
return(0); return (0);
} }
/* Check for quoted filenames */ /* Check for quoted filenames */
if (*cp == '\"' || *cp == '\'') { if (*cp == '\"' || *cp == '\'') {
quot = cp++; quot = *cp++;
for(i = 0; cp[i] && cp[i] != *quot; i++)
; end = strchr(cp, quot);
if (!cp[i]) { if (end == NULL) {
error("Unterminated quote"); error("Unterminated quote");
*path = NULL; goto fail;
return(-1);
} }
if (i == 0) { if (cp == end) {
error("Empty quotes"); error("Empty quotes");
*path = NULL; goto fail;
return(-1);
} }
*path = xmalloc(i + 1); *cpp = end + 1 + strspn(end + 1, WHITESPACE);
memcpy(*path, cp, i); } else {
(*path)[i] = '\0'; /* Read to end of filename */
cp += i + 1; end = strpbrk(cp, WHITESPACE);
*cpp = cp + strspn(cp, WHITESPACE); if (end == NULL)
return(0); end = strchr(cp, '\0');
*cpp = end + strspn(end, WHITESPACE);
} }
/* Read to end of filename */ i = end - cp;
for(i = 0; cp[i] && cp[i] != ' '; i++)
;
*path = xmalloc(i + 1); *path = xmalloc(i + 1);
memcpy(*path, cp, i); memcpy(*path, cp, i);
(*path)[i] = '\0'; (*path)[i] = '\0';
cp += i;
*cpp = cp + strspn(cp, WHITESPACE);
return(0); return(0);
fail:
*path = NULL;
return (-1);
} }
int int
@ -270,7 +274,6 @@ infer_path(const char *p, char **ifp)
debug("XXX: P = \"%s\"", p); debug("XXX: P = \"%s\"", p);
cp = strrchr(p, '/'); cp = strrchr(p, '/');
if (cp == NULL) { if (cp == NULL) {
*ifp = xstrdup(p); *ifp = xstrdup(p);
return(0); return(0);
@ -421,14 +424,13 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
} }
*cpp = cp; *cpp = cp;
return(cmdnum); return(cmdnum);
} }
int int
parse_dispatch_command(int in, int out, const char *cmd, char **pwd) parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
{ {
char *path1, *path2; char *path1, *path2, *tmp;
int pflag, cmdnum; int pflag, cmdnum;
unsigned long n_arg; unsigned long n_arg;
Attrib a, *aa; Attrib a, *aa;
@ -471,12 +473,44 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
break; break;
case I_CHDIR: case I_CHDIR:
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
if ((tmp = do_realpath(in, out, path1)) == NULL)
break;
if ((aa = do_stat(in, out, tmp)) == NULL) {
xfree(tmp);
break;
}
if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
error("Can't change directory: Can't check target");
xfree(tmp);
break;
}
if (!S_ISDIR(aa->perm)) {
error("Can't change directory: \"%s\" is not "
"a directory", tmp);
xfree(tmp);
break;
}
xfree(*pwd); xfree(*pwd);
*pwd = do_realpath(in, out, path1); *pwd = tmp;
break; break;
case I_LS: case I_LS:
if (!path1) {
do_ls(in, out, *pwd);
break;
}
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
do_ls(in, out, path1?path1:*pwd); if ((tmp = do_realpath(in, out, path1)) == NULL)
break;
xfree(path1);
path1 = tmp;
if ((aa = do_stat(in, out, path1)) == NULL)
break;
if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
!S_ISDIR(aa->perm)) {
error("Can't ls: \"%s\" is not a directory", path1);
break;
}
do_ls(in, out, path1);
break; break;
case I_LCHDIR: case I_LCHDIR:
if (chdir(path1) == -1) if (chdir(path1) == -1)
@ -485,7 +519,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
break; break;
case I_LMKDIR: case I_LMKDIR:
if (mkdir(path1, 0777) == -1) if (mkdir(path1, 0777) == -1)
error("Couldn't create local directory to " error("Couldn't create local directory "
"\"%s\": %s", path1, strerror(errno)); "\"%s\": %s", path1, strerror(errno));
break; break;
case I_LLS: case I_LLS:
@ -506,23 +540,27 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
break; break;
case I_CHOWN: case I_CHOWN:
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
aa = do_stat(in, out, path1); if (!(aa = do_stat(in, out, path1)))
break;
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of " error("Can't get current ownership of "
"remote file \"%s\"", path1); "remote file \"%s\"", path1);
break; break;
} }
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->uid = n_arg; aa->uid = n_arg;
do_setstat(in, out, path1, aa); do_setstat(in, out, path1, aa);
break; break;
case I_CHGRP: case I_CHGRP:
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
aa = do_stat(in, out, path1); if (!(aa = do_stat(in, out, path1)))
break;
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of " error("Can't get current ownership of "
"remote file \"%s\"", path1); "remote file \"%s\"", path1);
break; break;
} }
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->gid = n_arg; aa->gid = n_arg;
do_setstat(in, out, path1, aa); do_setstat(in, out, path1, aa);
break; break;
@ -550,7 +588,6 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
xfree(path1); xfree(path1);
if (path2) if (path2)
xfree(path2); xfree(path2);
return(0); return(0);
} }
@ -564,8 +601,8 @@ interactive_loop(int fd_in, int fd_out)
if (pwd == NULL) if (pwd == NULL)
fatal("Need cwd"); fatal("Need cwd");
setvbuf(stdout, (char *)NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stdin, (char *)NULL, _IOLBF, 0); setvbuf(stdin, NULL, _IOLBF, 0);
for(;;) { for(;;) {
char *cp; char *cp;

121
sftp.1
View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.1 2001/02/04 11:11:54 djm Exp $ .\" $OpenBSD: sftp.1,v 1.5 2001/02/07 18:10:39 stevesk Exp $
.\" .\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\" .\"
@ -30,7 +30,7 @@
.Nd Secure file tranfer program .Nd Secure file tranfer program
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm sftp .Nm sftp
.Op Fl v Li | Fl C .Op Fl vC
.Op Fl o Ar ssh_option .Op Fl o Ar ssh_option
.Op Ar hostname | user@hostname .Op Ar hostname | user@hostname
.Sh DESCRIPTION .Sh DESCRIPTION
@ -44,113 +44,122 @@ It may also use many features of ssh, such as public key authentication and
compression. compression.
.Nm .Nm
connects and logs into the specified connects and logs into the specified
.Ar hostname .Ar hostname ,
then enters an interactive command mode. then enters an interactive command mode.
.Pp .Pp
The options are as follows: The options are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl v
Raise logging level. This option is also passed to ssh.
.It Fl C .It Fl C
Enables compression (via ssh's Enables compression (via ssh's
.Fl C .Fl C
flag) flag)
.It Fl v
Raise logging level. This option is also passed to ssh.
.It Fl o Ar ssh_option .It Fl o Ar ssh_option
Specify an option to be directly passed to Specify an option to be directly passed to
.Xr ssh 1 . .Xr ssh 1 .
.El .El
.Sh INTERACTIVE COMMANDS .Sh INTERACTIVE COMMANDS
Once in interactive mode Once in interactive mode,
.Nm , .Nm
understands a set of commands similar to those of understands a set of commands similar to those of
.Xr ftp 1 . .Xr ftp 1 .
Commands are case insensitive. Commands are case insensitive.
.Bl -tag -width Ds .Bl -tag -width Ds
.It Ic CD Ar path .It Ic cd Ar path
Change remote directory to Change remote directory to
.Ar path .Ar path .
.It Ic LCD Ar path .It Ic lcd Ar path
Change local directory to Change local directory to
.Ar path .Ar path .
.It Ic CHGRP Ar grp Ar path .It Ic chgrp Ar grp Ar path
Change group of file Change group of file
.Ar path to .Ar path
to
.Ar grp . .Ar grp .
.Ar grp .Ar grp
must be numeric. must be a numeric GID.
.It Ic CHMOD Ar mode Ar path .It Ic chmod Ar mode Ar path
Change permissions of file Change permissions of file
.Ar path to .Ar path
.Ar mode to
.It Ic CHOWN Ar own Ar path .Ar mode .
.It Ic chown Ar own Ar path
Change owner of file Change owner of file
.Ar path to .Ar path
to
.Ar own . .Ar own .
.Ar own .Ar own
must be a numeric UID. must be a numeric UID.
.It Ic HELP .It Ic help
Display help text Display help text.
.It Ic GET Ar remote-file Op Ar local-file .It Ic get Ar remote-path Op Ar local-path
Retrieve the Retrieve the
.Ar remote-file .Ar remote-path
and store it on the local machine. and store it on the local machine.
If the local If the local
file name is not specified, it is given the same name it has on the path name is not specified, it is given the same name it has on the
remote machine. remote machine.
.It Ic LLS Op Ar ls-options Op Ar path .It Ic lls Op Ar ls-options Op Ar path
Display local directory listing of either Display local directory listing of either
.Ar path .Ar path
or current directory if or current directory if
.Ar path .Ar path
was not specified. is not specified.
.It Ic LMKDIR Ar path .It Ic lmkdir Ar path
Create local directory specified by Create local directory specified by
.Ar path .Ar path .
.It Ic LPWD .It Ic lpwd
Print local working directory Print local working directory.
.It Ic LS Op Ar path .It Ic ls Op Ar path
Display remote directory listing of either Display remote directory listing of either
.Ar path .Ar path
or current directory, is or current directory if
.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 .Ar path
.It Ic PUT local-file Op Ar remote-file is 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 Ar local-path Op Ar remote-path
Upload Upload
.Ar local-file .Ar local-path
and store it on the remote machine. If the local file name is not specified, and store it on the remote machine. If the remote path name is not specified,
it is given the same name it has on the local machine. it is given the same name it has on the local machine.
.It Ic PWD .It Ic pwd
Display remote working directory Display remote working directory.
.It Ic EXIT .It Ic exit
Quit sftp Quit sftp.
.It Ic QUIT .It Ic quit
Quit sftp Quit sftp.
.It Ic RENAME Ar oldpath Ar newpath .It Ic rename Ar oldpath Ar newpath
Rename remote file from Rename remote file from
.Ar oldpath .Ar oldpath
to to
.Ar newpath .Ar newpath .
.It Ic RMDIR Ar path .It Ic rmdir Ar path
Remove remote directory specified by Remove remote directory specified by
.Ar path .Ar path .
.It Ic RM Ar path .It Ic rm Ar path
Delete remote file specified by Delete remote file specified by
.Ar path .Ar path .
.It Ic ! Ar command .It Ic ! Ar command
Execute Execute
.Ar command .Ar command
in local shell in local shell.
.It Ic ! .It Ic !
Escape to local shell Escape to local shell.
.It Ic ?
Synonym for help.
.El
.Sh AUTHORS .Sh AUTHORS
Damien Miller <djm@mindrot.org> Damien Miller <djm@mindrot.org>
.Sh SEE ALSO .Sh SEE ALSO
.Xr ssh 1 , .Xr ssh 1 ,
.Xr ssh-add 1 , .Xr ssh-add 1 ,
.Xr ssh-keygen 1 , .Xr ssh-keygen 1 ,
.Xr sshd 8 .Xr sshd 8 ,
.Xr scp 1

97
sftp.c
View File

@ -24,7 +24,7 @@
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sftp.c,v 1.2 2001/02/04 15:32:25 stevesk Exp $"); RCSID("$OpenBSD: sftp.c,v 1.7 2001/02/08 00:04:52 markus Exp $");
/* XXX: commandline mode */ /* XXX: commandline mode */
/* XXX: copy between two remote hosts (commandline) */ /* XXX: copy between two remote hosts (commandline) */
@ -40,6 +40,10 @@ RCSID("$OpenBSD: sftp.c,v 1.2 2001/02/04 15:32:25 stevesk Exp $");
#include "sftp-client.h" #include "sftp-client.h"
#include "sftp-int.h" #include "sftp-int.h"
int use_ssh1 = 0;
char *ssh_program = _PATH_SSH_PROGRAM;
char *sftp_server = NULL;
void void
connect_to_server(char **args, int *in, int *out, pid_t *sshpid) connect_to_server(char **args, int *in, int *out, pid_t *sshpid)
{ {
@ -72,8 +76,8 @@ connect_to_server(char **args, int *in, int *out, pid_t *sshpid)
close(*out); close(*out);
close(c_in); close(c_in);
close(c_out); close(c_out);
execv(_PATH_SSH_PROGRAM, args); execv(ssh_program, args);
fprintf(stderr, "exec: %s", strerror(errno)); fprintf(stderr, "exec: %s: %s\n", ssh_program, strerror(errno));
exit(1); exit(1);
} }
@ -87,16 +91,24 @@ make_ssh_args(char *add_arg)
static char **args = NULL; static char **args = NULL;
static int nargs = 0; static int nargs = 0;
char debug_buf[4096]; char debug_buf[4096];
int i; int i, use_subsystem = 1;
/* no subsystem if protocol 1 or the server-spec contains a '/' */
if (use_ssh1 ||
(sftp_server != NULL && strchr(sftp_server, '/') != NULL))
use_subsystem = 0;
/* Init args array */ /* Init args array */
if (args == NULL) { if (args == NULL) {
nargs = 4; nargs = use_subsystem ? 6 : 5;
i = 0; i = 0;
args = xmalloc(sizeof(*args) * nargs); args = xmalloc(sizeof(*args) * nargs);
args[i++] = "ssh"; args[i++] = "ssh";
args[i++] = "-oProtocol=2"; args[i++] = use_ssh1 ? "-oProtocol=1" : "-oProtocol=2";
args[i++] = "-s"; if (use_subsystem)
args[i++] = "-s";
args[i++] = "-oForwardAgent=no";
args[i++] = "-oForwardX11=no";
args[i++] = NULL; args[i++] = NULL;
} }
@ -110,7 +122,10 @@ make_ssh_args(char *add_arg)
} }
/* Otherwise finish up and return the arg array */ /* Otherwise finish up and return the arg array */
make_ssh_args("sftp"); if (sftp_server != NULL)
make_ssh_args(sftp_server);
else
make_ssh_args("sftp");
/* XXX: overflow - doesn't grow debug_buf */ /* XXX: overflow - doesn't grow debug_buf */
debug_buf[0] = '\0'; debug_buf[0] = '\0';
@ -128,49 +143,70 @@ make_ssh_args(char *add_arg)
void void
usage(void) usage(void)
{ {
fprintf(stderr, "usage: sftp [-vC] [-osshopt=value] [user@]host\n"); fprintf(stderr, "usage: sftp [-1vC] [-osshopt=value] [user@]host\n");
exit(1); exit(1);
} }
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int in, out, i, debug_level, compress_flag; int in, out, ch, debug_level, compress_flag;
pid_t sshpid; pid_t sshpid;
char *cp; char *host, *userhost;
LogLevel ll; LogLevel ll;
extern int optind;
extern char *optarg;
debug_level = compress_flag = 0; debug_level = compress_flag = 0;
for(i = 1; i < argc && argv[i][0] == '-'; i++) {
if (!strcmp(argv[i], "-v")) while ((ch = getopt(argc, argv, "1hvCo:s:S:")) != -1) {
debug_level = MIN(3, debug_level + 1); switch (ch) {
else if (!strcmp(argv[i], "-C")) case 'C':
compress_flag = 1; compress_flag = 1;
else if (!strncmp(argv[i], "-o", 2)) { break;
make_ssh_args(argv[i]); case 'v':
} else { debug_level = MIN(3, debug_level + 1);
fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); break;
case 'o':
make_ssh_args("-o");
make_ssh_args(optarg);
break;
case '1':
use_ssh1 = 1;
if (sftp_server == NULL)
sftp_server = _PATH_SFTP_SERVER;
break;
case 's':
sftp_server = optarg;
break;
case 'S':
ssh_program = optarg;
break;
case 'h':
default:
usage(); usage();
} }
} }
if (i == argc || argc > (i + 1)) if (optind == argc || argc > (optind + 1))
usage(); usage();
if ((cp = strchr(argv[i], '@')) == NULL) userhost = argv[optind];
cp = argv[i];
if ((host = strchr(userhost, '@')) == NULL)
host = userhost;
else { else {
*cp = '\0'; *host = '\0';
if (!argv[i][0]) { if (!userhost[0]) {
fprintf(stderr, "Missing username\n"); fprintf(stderr, "Missing username\n");
usage(); usage();
} }
make_ssh_args("-l"); make_ssh_args("-l");
make_ssh_args(argv[i]); make_ssh_args(userhost);
cp++; host++;
} }
if (!*cp) { if (!*host) {
fprintf(stderr, "Missing hostname\n"); fprintf(stderr, "Missing hostname\n");
usage(); usage();
} }
@ -200,9 +236,9 @@ main(int argc, char **argv)
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
make_ssh_args(cp); make_ssh_args(host);
fprintf(stderr, "Connecting to %s...\n", cp); fprintf(stderr, "Connecting to %s...\n", host);
connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid); connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid);
@ -216,7 +252,8 @@ main(int argc, char **argv)
if (kill(sshpid, SIGHUP) == -1) if (kill(sshpid, SIGHUP) == -1)
fatal("Couldn't terminate ssh process: %s", strerror(errno)); fatal("Couldn't terminate ssh process: %s", strerror(errno));
/* XXX: wait? */ if (waitpid(sshpid, NULL, 0) == -1)
fatal("Couldn't wait for ssh process: %s", strerror(errno));
exit(0); exit(0);
} }