- 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:
parent
8ac0a7ec44
commit
058316f0f1
|
@ -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 $
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
29
sftp-int.c
29
sftp-int.c
|
@ -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");
|
||||
|
|
|
@ -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
18
sftp.1
|
@ -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
4
sftp.c
|
@ -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
9
sftp.h
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue