summaryrefslogtreecommitdiff
path: root/sftp-int.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2001-02-10 00:40:03 +1100
committerDamien Miller <djm@mindrot.org>2001-02-10 00:40:03 +1100
commitd7686fd1fbe842baa8ce77f018c040d5e1d3438a (patch)
treea5d6ad5b4b232e06185a49b1b5aabe4761a3d8ed /sftp-int.c
parent4192c467916f96668fad5b53d90d83dfbfdcacb5 (diff)
- (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
Diffstat (limited to 'sftp-int.c')
-rw-r--r--sftp-int.c199
1 files changed, 118 insertions, 81 deletions
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;