- (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
- (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 $

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@
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

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>
@ -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

View File

@ -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;
}

View File

@ -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:

View File

@ -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;

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.
.\"
@ -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
Set local umask to
.Ar umask
.It Ic MKDIR Ar path
Create remote directory specified by
or current directory if
.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
.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

97
sftp.c
View File

@ -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);
}