- OpenBSD CVS Sync

- djm@cvs.openbsd.org 2001/03/07 10:11:23
    [sftp-client.c sftp-client.h sftp-int.c sftp-server.c sftp.1 sftp.c sftp.h]
    Support for new draft (draft-ietf-secsh-filexfer-01). New symlink handling
    functions and small protocol change.
This commit is contained in:
Damien Miller 2001-03-08 10:08:49 +11:00
parent 8ac0a7ec44
commit 058316f0f1
8 changed files with 216 additions and 22 deletions

View File

@ -1,3 +1,10 @@
20010308
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2001/03/07 10:11:23
[sftp-client.c sftp-client.h sftp-int.c sftp-server.c sftp.1 sftp.c sftp.h]
Support for new draft (draft-ietf-secsh-filexfer-01). New symlink handling
functions and small protocol change.
20010307
- (bal) OpenBSD CVS Sync
- deraadt@cvs.openbsd.org 2001/03/06 06:11:18
@ -4430,4 +4437,4 @@
- Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1
$Id: ChangeLog,v 1.924 2001/03/07 10:38:19 djm Exp $
$Id: ChangeLog,v 1.925 2001/03/07 23:08:49 djm Exp $

View File

@ -29,7 +29,7 @@
/* XXX: copy between two remote sites */
#include "includes.h"
RCSID("$OpenBSD: sftp-client.c,v 1.10 2001/02/14 09:46:03 djm Exp $");
RCSID("$OpenBSD: sftp-client.c,v 1.11 2001/03/07 10:11:22 djm Exp $");
#include "ssh.h"
#include "buffer.h"
@ -247,7 +247,8 @@ do_init(int fd_in, int fd_out)
}
buffer_free(&msg);
return(0);
return(version);
}
int
@ -483,8 +484,7 @@ do_realpath(int fd_in, int fd_out, char *path)
Attrib *a;
expected_id = id = msg_id++;
send_string_request(fd_out, id, SSH2_FXP_REALPATH, path,
strlen(path));
send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path));
buffer_init(&msg);
@ -548,6 +548,79 @@ do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)
return(status);
}
int
do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath)
{
Buffer msg;
u_int status, id;
buffer_init(&msg);
/* Send rename request */
id = msg_id++;
buffer_put_char(&msg, SSH2_FXP_SYMLINK);
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, oldpath);
buffer_put_cstring(&msg, newpath);
send_msg(fd_out, &msg);
debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
newpath);
buffer_free(&msg);
status = get_status(fd_in, id);
if (status != SSH2_FX_OK)
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath,
fx2txt(status));
return(status);
}
char *
do_readlink(int fd_in, int fd_out, char *path)
{
Buffer msg;
u_int type, expected_id, count, id;
char *filename, *longname;
Attrib *a;
expected_id = id = msg_id++;
send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path));
buffer_init(&msg);
get_msg(fd_in, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
if (id != expected_id)
fatal("ID mismatch (%d != %d)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int status = buffer_get_int(&msg);
error("Couldn't readlink: %s", fx2txt(status));
return(NULL);
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%d) packet, got %d",
SSH2_FXP_NAME, type);
count = buffer_get_int(&msg);
if (count != 1)
fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
filename = buffer_get_string(&msg, NULL);
longname = buffer_get_string(&msg, NULL);
a = decode_attrib(&msg);
debug3("SSH_FXP_READLINK %s -> %s", path, filename);
xfree(longname);
buffer_free(&msg);
return(filename);
}
int
do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
int pflag)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.h,v 1.1 2001/02/04 11:11:54 djm Exp $ */
/* $OpenBSD: sftp-client.h,v 1.2 2001/03/07 10:11:23 djm Exp $ */
/*
* Copyright (c) 2001 Damien Miller. All rights reserved.
@ -26,7 +26,10 @@
/* Client side of SSH2 filexfer protocol */
/* Initialiase a SSH filexfer connection */
/*
* Initialiase a SSH filexfer connection. Returns -1 on error or
* protocol version on success.
*/
int do_init(int fd_in, int fd_out);
/* Close file referred to by 'handle' */
@ -67,6 +70,12 @@ char *do_realpath(int fd_in, int fd_out, char *path);
/* Rename 'oldpath' to 'newpath' */
int do_rename(int fd_in, int fd_out, char *oldpath, char *newpath);
/* Rename 'oldpath' to 'newpath' */
int do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath);
/* Return target of symlink 'path' - caller must free result */
char *do_readlink(int fd_in, int fd_out, char *path);
/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
/*

View File

@ -28,7 +28,7 @@
/* XXX: recursive operations */
#include "includes.h"
RCSID("$OpenBSD: sftp-int.c,v 1.25 2001/03/06 06:11:44 deraadt Exp $");
RCSID("$OpenBSD: sftp-int.c,v 1.26 2001/03/07 10:11:23 djm Exp $");
#include "buffer.h"
#include "xmalloc.h"
@ -40,7 +40,11 @@ RCSID("$OpenBSD: sftp-int.c,v 1.25 2001/03/06 06:11:44 deraadt Exp $");
#include "sftp-client.h"
#include "sftp-int.h"
extern FILE* infile;
/* File to read commands from */
extern FILE *infile;
/* Version of server we are speaking to */
int version;
/* Seperators for interactive commands */
#define WHITESPACE " \t\r\n"
@ -66,6 +70,7 @@ extern FILE* infile;
#define I_RM 18
#define I_RMDIR 19
#define I_SHELL 20
#define I_SYMLINK 21
struct CMD {
const char *c;
@ -86,6 +91,7 @@ const struct CMD cmds[] = {
{ "lchdir", I_LCHDIR },
{ "lls", I_LLS },
{ "lmkdir", I_LMKDIR },
{ "ln", I_SYMLINK },
{ "lpwd", I_LPWD },
{ "ls", I_LS },
{ "lumask", I_LUMASK },
@ -96,6 +102,7 @@ const struct CMD cmds[] = {
{ "rename", I_RENAME },
{ "rm", I_RM },
{ "rmdir", I_RMDIR },
{ "symlink", I_SYMLINK },
{ "!", I_SHELL },
{ "?", I_HELP },
{ NULL, -1}
@ -113,6 +120,7 @@ help(void)
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("ln oldpath newpath Symlink remote file\n");
printf("lmkdir path Create local directory\n");
printf("lpwd Print local working directory\n");
printf("ls [path] Display remote directory listing\n");
@ -125,6 +133,7 @@ help(void)
printf("rename oldpath newpath Rename remote file\n");
printf("rmdir path Remove remote directory\n");
printf("rm path Delete remote file\n");
printf("symlink oldpath newpath Symlink remote file\n");
printf("!command Execute 'command' in local shell\n");
printf("! Escape to local shell\n");
printf("? Synonym for help\n");
@ -356,7 +365,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
return(-1);
break;
case I_RENAME:
/* Get first pathname (mandatory) */
case I_SYMLINK:
if (get_pathname(&cp, path1))
return(-1);
if (get_pathname(&cp, path2))
@ -468,6 +477,16 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
path2 = make_absolute(path2, *pwd);
err = do_rename(in, out, path1, path2);
break;
case I_SYMLINK:
if (version < 3) {
error("The server (version %d) does not support "
"this operation", version);
err = -1;
} else {
path2 = make_absolute(path2, *pwd);
err = do_symlink(in, out, path1, path2);
}
break;
case I_RM:
path1 = make_absolute(path1, *pwd);
err = do_rm(in, out, path1);
@ -624,6 +643,10 @@ interactive_loop(int fd_in, int fd_out)
char *pwd;
char cmd[2048];
version = do_init(fd_in, fd_out);
if (version == -1)
fatal("Couldn't initialise connection to server");
pwd = do_realpath(fd_in, fd_out, ".");
if (pwd == NULL)
fatal("Need cwd");

View File

@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: sftp-server.c,v 1.22 2001/03/03 22:07:50 deraadt Exp $");
RCSID("$OpenBSD: sftp-server.c,v 1.23 2001/03/07 10:11:23 djm Exp $");
#include "buffer.h"
#include "bufaux.h"
@ -49,6 +49,9 @@ char *__progname;
Buffer iqueue;
Buffer oqueue;
/* Version of client */
int version;
/* portable attibutes, etc. */
typedef struct Stat Stat;
@ -266,12 +269,29 @@ void
send_status(u_int32_t id, u_int32_t error)
{
Buffer msg;
const char *status_messages[] = {
"Success", /* SSH_FX_OK */
"End of file", /* SSH_FX_EOF */
"No such file", /* SSH_FX_NO_SUCH_FILE */
"Permission denied", /* SSH_FX_PERMISSION_DENIED */
"Failure", /* SSH_FX_FAILURE */
"Bad message", /* SSH_FX_BAD_MESSAGE */
"No connection", /* SSH_FX_NO_CONNECTION */
"Connection lost", /* SSH_FX_CONNECTION_LOST */
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
"Unknown error" /* Others */
};
TRACE("sent status id %d error %d", id, error);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_STATUS);
buffer_put_int(&msg, id);
buffer_put_int(&msg, error);
if (version >= 3) {
buffer_put_cstring(&msg,
status_messages[MIN(error,SSH2_FX_MAX)]);
buffer_put_cstring(&msg, "");
}
send_msg(&msg);
buffer_free(&msg);
}
@ -347,8 +367,8 @@ void
process_init(void)
{
Buffer msg;
int version = buffer_get_int(&iqueue);
version = buffer_get_int(&iqueue);
TRACE("client version %d", version);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_VERSION);
@ -859,6 +879,51 @@ process_rename(void)
xfree(newpath);
}
void
process_readlink(void)
{
u_int32_t id;
char link[MAXPATHLEN];
char *path;
id = get_int();
path = get_string(NULL);
TRACE("readlink id %d path %s", id, path);
if (readlink(path, link, sizeof(link) - 1) == -1)
send_status(id, errno_to_portable(errno));
else {
Stat s;
link[sizeof(link) - 1] = '\0';
attrib_clear(&s.attrib);
s.name = s.long_name = link;
send_names(id, 1, &s);
}
xfree(path);
}
void
process_symlink(void)
{
u_int32_t id;
struct stat st;
char *oldpath, *newpath;
int ret, status = SSH2_FX_FAILURE;
id = get_int();
oldpath = get_string(NULL);
newpath = get_string(NULL);
TRACE("symlink id %d old %s new %s", id, oldpath, newpath);
/* fail if 'newpath' exists */
if (stat(newpath, &st) == -1) {
ret = symlink(oldpath, newpath);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
}
send_status(id, status);
xfree(oldpath);
xfree(newpath);
}
void
process_extended(void)
{
@ -944,6 +1009,12 @@ process(void)
case SSH2_FXP_RENAME:
process_rename();
break;
case SSH2_FXP_READLINK:
process_readlink();
break;
case SSH2_FXP_SYMLINK:
process_symlink();
break;
case SSH2_FXP_EXTENDED:
process_extended();
break;

18
sftp.1
View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.11 2001/03/06 15:10:42 deraadt Exp $
.\" $OpenBSD: sftp.1,v 1.12 2001/03/07 10:11:23 djm Exp $
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\"
@ -58,7 +58,7 @@ instead of
Since it lacks user interaction it should be used in conjuction with a
non-interactive authentication. Sftp will abort if any of the following
commands fail:
.Pa get, put, rename, rm, mkdir, chdir, lchdir
.Pa get, put, rename, ln, rm, mkdir, chdir, lchdir
and
.Pa lmkdir.
.It Fl C
@ -131,6 +131,11 @@ is not specified.
.It Ic lmkdir Ar path
Create local directory specified by
.Ar path .
.It Ic ln Ar oldpath Ar newpath
Create a symbolic link from
.Ar oldpath
to
.Ar newpath .
.It Ic lpwd
Print local working directory.
.It Ic ls Op Ar path
@ -152,8 +157,8 @@ Create remote directory specified by
.Xc
Upload
.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. If the
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. If the
.Fl P
flag is specified, then the file's full permission and access time are
copied too.
@ -172,6 +177,11 @@ Remove remote directory specified by
.It Ic rm Ar path
Delete remote file specified by
.Ar path .
.It Ic symlink Ar oldpath Ar newpath
Create a symbolic link from
.Ar oldpath
to
.Ar newpath .
.It Ic ! Ar command
Execute
.Ar command

4
sftp.c
View File

@ -24,7 +24,7 @@
#include "includes.h"
RCSID("$OpenBSD: sftp.c,v 1.10 2001/03/06 06:11:44 deraadt Exp $");
RCSID("$OpenBSD: sftp.c,v 1.11 2001/03/07 10:11:23 djm Exp $");
/* XXX: commandline mode */
/* XXX: copy between two remote hosts (commandline) */
@ -256,8 +256,6 @@ main(int argc, char **argv)
connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid);
do_init(in, out);
interactive_loop(in, out);
#if !defined(USE_PIPES)

9
sftp.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.h,v 1.2 2001/01/29 01:58:18 niklas Exp $ */
/* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -25,11 +25,11 @@
*/
/*
* draft-ietf-secsh-filexfer-00.txt
* draft-ietf-secsh-filexfer-01.txt
*/
/* version */
#define SSH2_FILEXFER_VERSION 2
#define SSH2_FILEXFER_VERSION 3
/* client to server */
#define SSH2_FXP_INIT 1
@ -49,6 +49,8 @@
#define SSH2_FXP_REALPATH 16
#define SSH2_FXP_STAT 17
#define SSH2_FXP_RENAME 18
#define SSH2_FXP_READLINK 19
#define SSH2_FXP_SYMLINK 20
/* server to client */
#define SSH2_FXP_VERSION 2
@ -86,3 +88,4 @@
#define SSH2_FX_NO_CONNECTION 6
#define SSH2_FX_CONNECTION_LOST 7
#define SSH2_FX_OP_UNSUPPORTED 8
#define SSH2_FX_MAX 8