summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog66
-rw-r--r--Makefile.in13
-rw-r--r--pathnames.h8
-rw-r--r--sftp-client.c51
-rw-r--r--sftp-common.c10
-rw-r--r--sftp-int.c199
-rw-r--r--sftp.1119
-rw-r--r--sftp.c97
8 files changed, 363 insertions, 200 deletions
diff --git a/ChangeLog b/ChangeLog
index 601f3017..966b073c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
- (bal) patch to vis.c to deal with HAVE_VIS right by Robert Mooney
<rjmooney@mediaone.net>
@@ -3703,4 +3767,4 @@
- Wrote replacements for strlcpy and mkdtemp
- 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 $
diff --git a/Makefile.in b/Makefile.in
index af82ea15..f64e2550 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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@
exec_prefix=@exec_prefix@
@@ -16,10 +16,15 @@ DESTDIR=
VPATH=@srcdir@
SSH_PROGRAM=@bindir@/ssh
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@
LD=@LD@
-PATHS=-DETCDIR=\"$(sysconfdir)\" -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\"
CFLAGS=@CFLAGS@
CPPFLAGS=@CPPFLAGS@ -I. -I$(srcdir)/openbsd-compat -I$(srcdir) $(PATHS) @DEFS@
LIBS=@LIBS@
@@ -162,7 +167,7 @@ install-files:
$(INSTALL) -m 0775 -s ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan
$(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd
@NO_SFTP@$(INSTALL) -m 0755 -s sftp $(DESTDIR)$(bindir)/sftp
- @NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(libexecdir)/sftp-server
+ @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 scp.[01].out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.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)/sftp$(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/scp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
diff --git a/pathnames.h b/pathnames.h
index 85d8a1fe..3f116bdb 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -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>
@@ -116,6 +116,12 @@
#define _PATH_CP "cp"
#endif
+/* for sftp */
+#ifndef _PATH_SFTP_SERVER
+#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server"
+#endif
+#define _PATH_LS "ls"
+
/* path to login program */
#ifndef LOGIN_PROGRAM
# ifdef LOGIN_PROGRAM_FALLBACK
diff --git a/sftp-client.c b/sftp-client.c
index e8b9007f..490c00bd 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -29,7 +29,7 @@
/* XXX: copy between two remote sites */
#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 "buffer.h"
@@ -338,7 +338,9 @@ do_ls(int fd_in, int fd_out, char *path)
SSH2_FXP_NAME, type);
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++) {
char *filename, *longname;
Attrib *a;
@@ -556,6 +558,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
char *handle;
Buffer msg;
Attrib junk, *a;
+ int status;
a = do_stat(fd_in, fd_out, remote_path);
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)
fatal("ID mismatch (%d != %d)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
- int status = buffer_get_int(&msg);
+ status = buffer_get_int(&msg);
if (status == SSH2_FX_EOF)
break;
@@ -644,10 +647,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
"file \"%s\" : %s", remote_path,
fx2txt(status));
do_close(fd_in, fd_out, handle, handle_len);
- xfree(handle);
- close(local_fd);
- buffer_free(&msg);
- return(status);
+ goto done;
}
} else if (type != SSH2_FXP_DATA) {
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",
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);
if (atomicio(write, local_fd, data, len) != len) {
error("Couldn't write to \"%s\": %s", local_path,
strerror(errno));
do_close(fd_in, fd_out, handle, handle_len);
- xfree(handle);
- close(local_fd);
+ status = -1;
xfree(data);
- buffer_free(&msg);
- return(-1);
+ goto done;
}
offset += len;
xfree(data);
}
- xfree(handle);
- buffer_free(&msg);
- close(local_fd);
+ status = do_close(fd_in, fd_out, handle, handle_len);
- return(do_close(fd_in, fd_out, handle, handle_len));
+done:
+ close(local_fd);
+ buffer_free(&msg);
+ xfree(handle);
+ return status;
}
int
@@ -693,6 +693,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
Buffer msg;
struct stat sb;
Attrib a;
+ int status;
if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
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(;;) {
int len;
char data[COPY_SIZE];
- u_int status;
/*
* 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",
remote_path, fx2txt(status));
do_close(fd_in, fd_out, handle, handle_len);
- xfree(handle);
close(local_fd);
- return(-1);
+ goto done;
}
debug3("In write loop, got %d offset %llu", len,
(unsigned long long)offset);
offset += len;
}
- xfree(handle);
- buffer_free(&msg);
if (close(local_fd) == -1) {
error("Couldn't close local file \"%s\": %s", local_path,
strerror(errno));
do_close(fd_in, fd_out, handle, handle_len);
- return(-1);
+ 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;
}
+
+
diff --git a/sftp-common.c b/sftp-common.c
index aed9b339..3310eaba 100644
--- a/sftp-common.c
+++ b/sftp-common.c
@@ -24,7 +24,7 @@
*/
#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 "bufaux.h"
@@ -121,13 +121,13 @@ fx2txt(int status)
{
switch (status) {
case SSH2_FX_OK:
- return("No Error");
+ return("No error");
case SSH2_FX_EOF:
- return("End of File");
+ return("End of file");
case SSH2_FX_NO_SUCH_FILE:
- return("No Such File");
+ return("No such file or directory");
case SSH2_FX_PERMISSION_DENIED:
- return("Permission Denied");
+ return("Permission denied");
case SSH2_FX_FAILURE:
return("Failure");
case SSH2_FX_BAD_MESSAGE:
diff --git a/sftp-int.c b/sftp-int.c
index 02e0d38c..8b5ae3ae 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -24,10 +24,11 @@
/* XXX: finish implementation of all commands */
/* XXX: do fnmatch() instead of using raw pathname */
+/* XXX: globbed ls */
/* XXX: recursive operations */
#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 "xmalloc.h"
@@ -70,28 +71,29 @@ struct CMD {
};
const struct CMD cmds[] = {
- { "CD", I_CHDIR },
- { "CHDIR", I_CHDIR },
- { "CHGRP", I_CHGRP },
- { "CHMOD", I_CHMOD },
- { "CHOWN", I_CHOWN },
- { "EXIT", I_QUIT },
- { "GET", I_GET },
- { "HELP", I_HELP },
- { "LCD", I_LCHDIR },
- { "LCHDIR", I_LCHDIR },
- { "LLS", I_LLS },
- { "LMKDIR", I_LMKDIR },
- { "LPWD", I_LPWD },
- { "LS", I_LS },
- { "LUMASK", I_LUMASK },
- { "MKDIR", I_MKDIR },
- { "PUT", I_PUT },
- { "PWD", I_PWD },
- { "QUIT", I_QUIT },
- { "RENAME", I_RENAME },
- { "RM", I_RM },
- { "RMDIR", I_RMDIR },
+ { "cd", I_CHDIR },
+ { "chdir", I_CHDIR },
+ { "chgrp", I_CHGRP },
+ { "chmod", I_CHMOD },
+ { "chown", I_CHOWN },
+ { "dir", I_LS },
+ { "exit", I_QUIT },
+ { "get", I_GET },
+ { "help", I_HELP },
+ { "lcd", I_LCHDIR },
+ { "lchdir", I_LCHDIR },
+ { "lls", I_LLS },
+ { "lmkdir", I_LMKDIR },
+ { "lpwd", I_LPWD },
+ { "ls", I_LS },
+ { "lumask", I_LUMASK },
+ { "mkdir", I_MKDIR },
+ { "put", I_PUT },
+ { "pwd", I_PWD },
+ { "quit", I_QUIT },
+ { "rename", I_RENAME },
+ { "rm", I_RM },
+ { "rmdir", I_RMDIR },
{ "!", I_SHELL },
{ "?", I_HELP },
{ NULL, -1}
@@ -101,28 +103,29 @@ void
help(void)
{
printf("Available commands:\n");
- printf("CD path Change remote directory to 'path'\n");
- printf("LCD path Change local directory to 'path'\n");
- printf("CHGRP grp path Change group of file 'path' to 'grp'\n");
- printf("CHMOD mode path Change permissions of file 'path' to 'mode'\n");
- printf("CHOWN own path Change owner of file 'path' to 'own'\n");
- printf("HELP Display this help text\n");
- printf("GET remote-path [local-path] Download file\n");
- printf("LLS [ls options] [path] Display local directory listing\n");
- printf("LMKDIR path Create local directory\n");
- printf("LPWD Print local working directory\n");
- printf("LS [path] Display remote directory listing\n");
- printf("LUMASK umask Set local umask to 'umask'\n");
- printf("MKDIR path Create remote directory\n");
- printf("PUT local-path [remote-path] Upload file\n");
- printf("PWD Display remote working directory\n");
- printf("EXIT Quit sftp\n");
- printf("QUIT Quit sftp\n");
- printf("RENAME oldpath newpath Rename remote file\n");
- printf("RMDIR path Remove remote directory\n");
- printf("RM path Delete remote file\n");
+ printf("cd path Change remote directory to 'path'\n");
+ printf("lcd path Change local directory to 'path'\n");
+ printf("chgrp grp path Change group of file 'path' to 'grp'\n");
+ printf("chmod mode path Change permissions of file 'path' to 'mode'\n");
+ printf("chown own path Change owner of file 'path' to 'own'\n");
+ printf("help Display this help text\n");
+ printf("get remote-path [local-path] Download file\n");
+ printf("lls [ls-options [path]] Display local directory listing\n");
+ printf("lmkdir path Create local directory\n");
+ printf("lpwd Print local working directory\n");
+ printf("ls [path] Display remote directory listing\n");
+ printf("lumask umask Set local umask to 'umask'\n");
+ printf("mkdir path Create remote directory\n");
+ printf("put local-path [remote-path] Upload file\n");
+ printf("pwd Display remote working directory\n");
+ printf("exit Quit sftp\n");
+ printf("quit Quit sftp\n");
+ printf("rename oldpath newpath Rename remote file\n");
+ printf("rmdir path Remove remote directory\n");
+ printf("rm path Delete remote file\n");
printf("!command Execute 'command' in local shell\n");
printf("! Escape to local shell\n");
+ printf("? Synonym for help\n");
}
void
@@ -166,13 +169,15 @@ void
local_do_ls(const char *args)
{
if (!args || !*args)
- local_do_shell("ls");
+ local_do_shell(_PATH_LS);
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? */
- sprintf(buf, "/bin/ls %s", args);
+ snprintf(buf, len, _PATH_LS " %s", args);
local_do_shell(buf);
+ xfree(buf);
}
}
@@ -198,7 +203,7 @@ parse_getput_flags(const char **cpp, int *pflag)
/* Check for flags */
if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
- switch (*cp) {
+ switch (cp[1]) {
case 'P':
*pflag = 1;
break;
@@ -216,50 +221,49 @@ parse_getput_flags(const char **cpp, int *pflag)
int
get_pathname(const char **cpp, char **path)
{
- const char *quot, *cp = *cpp;
+ const char *cp = *cpp, *end;
+ char quot;
int i;
cp += strspn(cp, WHITESPACE);
if (!*cp) {
*cpp = cp;
*path = NULL;
- return(0);
+ return (0);
}
/* Check for quoted filenames */
if (*cp == '\"' || *cp == '\'') {
- quot = cp++;
- for(i = 0; cp[i] && cp[i] != *quot; i++)
- ;
- if (!cp[i]) {
+ quot = *cp++;
+
+ end = strchr(cp, quot);
+ if (end == NULL) {
error("Unterminated quote");
- *path = NULL;
- return(-1);
+ goto fail;
}
- if (i == 0) {
+ if (cp == end) {
error("Empty quotes");
- *path = NULL;
- return(-1);
+ goto fail;
}
- *path = xmalloc(i + 1);
- memcpy(*path, cp, i);
- (*path)[i] = '\0';
- cp += i + 1;
- *cpp = cp + strspn(cp, WHITESPACE);
- return(0);
+ *cpp = end + 1 + strspn(end + 1, WHITESPACE);
+ } else {
+ /* Read to end of filename */
+ end = strpbrk(cp, WHITESPACE);
+ if (end == NULL)
+ end = strchr(cp, '\0');
+ *cpp = end + strspn(end, WHITESPACE);
}
- /* Read to end of filename */
- for(i = 0; cp[i] && cp[i] != ' '; i++)
- ;
+ i = end - cp;
*path = xmalloc(i + 1);
memcpy(*path, cp, i);
(*path)[i] = '\0';
- cp += i;
- *cpp = cp + strspn(cp, WHITESPACE);
-
return(0);
+
+ fail:
+ *path = NULL;
+ return (-1);
}
int
@@ -270,7 +274,6 @@ infer_path(const char *p, char **ifp)
debug("XXX: P = \"%s\"", p);
cp = strrchr(p, '/');
-
if (cp == NULL) {
*ifp = xstrdup(p);
return(0);
@@ -421,14 +424,13 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
}
*cpp = cp;
-
return(cmdnum);
}
int
parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
{
- char *path1, *path2;
+ char *path1, *path2, *tmp;
int pflag, cmdnum;
unsigned long n_arg;
Attrib a, *aa;
@@ -471,12 +473,44 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
break;
case I_CHDIR:
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);
- *pwd = do_realpath(in, out, path1);
+ *pwd = tmp;
break;
case I_LS:
+ if (!path1) {
+ do_ls(in, out, *pwd);
+ break;
+ }
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;
case I_LCHDIR:
if (chdir(path1) == -1)
@@ -485,7 +519,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
break;
case I_LMKDIR:
if (mkdir(path1, 0777) == -1)
- error("Couldn't create local directory to "
+ error("Couldn't create local directory "
"\"%s\": %s", path1, strerror(errno));
break;
case I_LLS:
@@ -506,23 +540,27 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
break;
case I_CHOWN:
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)) {
error("Can't get current ownership of "
"remote file \"%s\"", path1);
break;
}
+ aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->uid = n_arg;
do_setstat(in, out, path1, aa);
break;
case I_CHGRP:
path1 = make_absolute(path1, *pwd);
- aa = do_stat(in, out, path1);
+ if (!(aa = do_stat(in, out, path1)))
+ break;
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of "
"remote file \"%s\"", path1);
break;
}
+ aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->gid = n_arg;
do_setstat(in, out, path1, aa);
break;
@@ -550,7 +588,6 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
xfree(path1);
if (path2)
xfree(path2);
-
return(0);
}
@@ -564,8 +601,8 @@ interactive_loop(int fd_in, int fd_out)
if (pwd == NULL)
fatal("Need cwd");
- setvbuf(stdout, (char *)NULL, _IOLBF, 0);
- setvbuf(stdin, (char *)NULL, _IOLBF, 0);
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(stdin, NULL, _IOLBF, 0);
for(;;) {
char *cp;
diff --git a/sftp.1 b/sftp.1
index 59206b65..84edc4d6 100644
--- a/sftp.1
+++ b/sftp.1
@@ -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.
.\"
@@ -30,7 +30,7 @@
.Nd Secure file tranfer program
.Sh SYNOPSIS
.Nm sftp
-.Op Fl v Li | Fl C
+.Op Fl vC
.Op Fl o Ar ssh_option
.Op Ar hostname | user@hostname
.Sh DESCRIPTION
@@ -44,113 +44,122 @@ It may also use many features of ssh, such as public key authentication and
compression.
.Nm
connects and logs into the specified
-.Ar hostname
+.Ar hostname ,
then enters an interactive command mode.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl v
+Raise logging level. This option is also passed to ssh.
.It Fl C
Enables compression (via ssh's
.Fl C
flag)
-.It Fl v
-Raise logging level. This option is also passed to ssh.
.It Fl o Ar ssh_option
Specify an option to be directly passed to
.Xr ssh 1 .
.El
.Sh INTERACTIVE COMMANDS
-Once in interactive mode
-.Nm ,
+Once in interactive mode,
+.Nm
understands a set of commands similar to those of
.Xr ftp 1 .
Commands are case insensitive.
.Bl -tag -width Ds
-.It Ic CD Ar path
+.It Ic cd Ar path
Change remote directory to
-.Ar path
-.It Ic LCD Ar path
+.Ar path .
+.It Ic lcd Ar path
Change local directory to
-.Ar path
-.It Ic CHGRP Ar grp Ar path
+.Ar path .
+.It Ic chgrp Ar grp Ar path
Change group of file
-.Ar path to
+.Ar path
+to
.Ar grp .
.Ar grp
-must be numeric.
-.It Ic CHMOD Ar mode Ar path
+must be a numeric GID.
+.It Ic chmod Ar mode Ar path
Change permissions of file
-.Ar path to
-.Ar mode
-.It Ic CHOWN Ar own Ar path
+.Ar path
+to
+.Ar mode .
+.It Ic chown Ar own Ar path
Change owner of file
-.Ar path to
+.Ar path
+to
.Ar own .
.Ar own
must be a numeric UID.
-.It Ic HELP
-Display help text
-.It Ic GET Ar remote-file Op Ar local-file
+.It Ic help
+Display help text.
+.It Ic get Ar remote-path Op Ar local-path
Retrieve the
-.Ar remote-file
+.Ar remote-path
and store it on the local machine.
If the local
-file name is not specified, it is given the same name it has on the
+path name is not specified, it is given the same name it has on the
remote machine.
-.It Ic LLS Op Ar ls-options Op Ar path
+.It Ic lls Op Ar ls-options Op Ar path
Display local directory listing of either
.Ar path
or current directory if
.Ar path
-was not specified.
-.It Ic LMKDIR Ar path
+is not specified.
+.It Ic lmkdir Ar path
Create local directory specified by
-.Ar path
-.It Ic LPWD
-Print local working directory
-.It Ic LS Op Ar path
+.Ar path .
+.It Ic lpwd
+Print local working directory.
+.It Ic ls Op Ar path
Display remote directory listing of either
.Ar path
-or current directory, is
-.Ar path not specified.
-.It Ic LUMASK Ar umask
+or current directory if
+.Ar path
+is not specified.
+.It Ic lumask Ar umask
Set local umask to
-.Ar umask
-.It Ic MKDIR Ar path
+.Ar umask .
+.It Ic mkdir Ar path
Create remote directory specified by
-.Ar path
-.It Ic PUT local-file Op Ar remote-file
+.Ar path .
+.It Ic put Ar local-path Op Ar remote-path
Upload
-.Ar local-file
-and store it on the remote machine. If the local file name is not specified,
+.Ar local-path
+and store it on the remote machine. If the remote path name is not specified,
it is given the same name it has on the local machine.
-.It Ic PWD
-Display remote working directory
-.It Ic EXIT
-Quit sftp
-.It Ic QUIT
-Quit sftp
-.It Ic RENAME Ar oldpath Ar newpath
+.It Ic pwd
+Display remote working directory.
+.It Ic exit
+Quit sftp.
+.It Ic quit
+Quit sftp.
+.It Ic rename Ar oldpath Ar newpath
Rename remote file from
.Ar oldpath
to
-.Ar newpath
-.It Ic RMDIR Ar path
+.Ar newpath .
+.It Ic rmdir Ar path
Remove remote directory specified by
-.Ar path
-.It Ic RM Ar path
+.Ar path .
+.It Ic rm Ar path
Delete remote file specified by
-.Ar path
+.Ar path .
.It Ic ! Ar command
Execute
.Ar command
-in local shell
+in local shell.
.It Ic !
-Escape to local shell
+Escape to local shell.
+.It Ic ?
+Synonym for help.
+.El
.Sh AUTHORS
Damien Miller <djm@mindrot.org>
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
-.Xr sshd 8
+.Xr sshd 8 ,
+.Xr scp 1
+
diff --git a/sftp.c b/sftp.c
index 27873d03..b4775c02 100644
--- a/sftp.c
+++ b/sftp.c
@@ -24,7 +24,7 @@
#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: 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-int.h"
+int use_ssh1 = 0;
+char *ssh_program = _PATH_SSH_PROGRAM;
+char *sftp_server = NULL;
+
void
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(c_in);
close(c_out);
- execv(_PATH_SSH_PROGRAM, args);
- fprintf(stderr, "exec: %s", strerror(errno));
+ execv(ssh_program, args);
+ fprintf(stderr, "exec: %s: %s\n", ssh_program, strerror(errno));
exit(1);
}
@@ -87,16 +91,24 @@ make_ssh_args(char *add_arg)
static char **args = NULL;
static int nargs = 0;
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 */
if (args == NULL) {
- nargs = 4;
+ nargs = use_subsystem ? 6 : 5;
i = 0;
args = xmalloc(sizeof(*args) * nargs);
args[i++] = "ssh";
- args[i++] = "-oProtocol=2";
- args[i++] = "-s";
+ args[i++] = use_ssh1 ? "-oProtocol=1" : "-oProtocol=2";
+ if (use_subsystem)
+ args[i++] = "-s";
+ args[i++] = "-oForwardAgent=no";
+ args[i++] = "-oForwardX11=no";
args[i++] = NULL;
}
@@ -110,7 +122,10 @@ make_ssh_args(char *add_arg)
}
/* 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 */
debug_buf[0] = '\0';
@@ -128,49 +143,70 @@ make_ssh_args(char *add_arg)
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);
}
int
main(int argc, char **argv)
{
- int in, out, i, debug_level, compress_flag;
+ int in, out, ch, debug_level, compress_flag;
pid_t sshpid;
- char *cp;
+ char *host, *userhost;
LogLevel ll;
+ extern int optind;
+ extern char *optarg;
debug_level = compress_flag = 0;
- for(i = 1; i < argc && argv[i][0] == '-'; i++) {
- if (!strcmp(argv[i], "-v"))
- debug_level = MIN(3, debug_level + 1);
- else if (!strcmp(argv[i], "-C"))
+
+ while ((ch = getopt(argc, argv, "1hvCo:s:S:")) != -1) {
+ switch (ch) {
+ case 'C':
compress_flag = 1;
- else if (!strncmp(argv[i], "-o", 2)) {
- make_ssh_args(argv[i]);
- } else {
- fprintf(stderr, "Unknown option \"%s\"\n", argv[i]);
+ break;
+ case 'v':
+ debug_level = MIN(3, debug_level + 1);
+ 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();
}
}
- if (i == argc || argc > (i + 1))
+ if (optind == argc || argc > (optind + 1))
usage();
- if ((cp = strchr(argv[i], '@')) == NULL)
- cp = argv[i];
+ userhost = argv[optind];
+
+ if ((host = strchr(userhost, '@')) == NULL)
+ host = userhost;
else {
- *cp = '\0';
- if (!argv[i][0]) {
+ *host = '\0';
+ if (!userhost[0]) {
fprintf(stderr, "Missing username\n");
usage();
}
make_ssh_args("-l");
- make_ssh_args(argv[i]);
- cp++;
+ make_ssh_args(userhost);
+ host++;
}
- if (!*cp) {
+ if (!*host) {
fprintf(stderr, "Missing hostname\n");
usage();
}
@@ -200,9 +236,9 @@ main(int argc, char **argv)
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);
@@ -216,7 +252,8 @@ main(int argc, char **argv)
if (kill(sshpid, SIGHUP) == -1)
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);
}