diff options
Diffstat (limited to 'sftp-int.c')
-rw-r--r-- | sftp-int.c | 199 |
1 files changed, 118 insertions, 81 deletions
diff --git a/sftp-int.c b/sftp-int.c index 02e0d38c0..8b5ae3aef 100644 --- a/sftp-int.c +++ b/sftp-int.c | |||
@@ -24,10 +24,11 @@ | |||
24 | 24 | ||
25 | /* XXX: finish implementation of all commands */ | 25 | /* XXX: finish implementation of all commands */ |
26 | /* XXX: do fnmatch() instead of using raw pathname */ | 26 | /* XXX: do fnmatch() instead of using raw pathname */ |
27 | /* XXX: globbed ls */ | ||
27 | /* XXX: recursive operations */ | 28 | /* XXX: recursive operations */ |
28 | 29 | ||
29 | #include "includes.h" | 30 | #include "includes.h" |
30 | RCSID("$OpenBSD: sftp-int.c,v 1.7 2001/02/05 00:02:32 deraadt Exp $"); | 31 | RCSID("$OpenBSD: sftp-int.c,v 1.19 2001/02/09 11:46:24 djm Exp $"); |
31 | 32 | ||
32 | #include "buffer.h" | 33 | #include "buffer.h" |
33 | #include "xmalloc.h" | 34 | #include "xmalloc.h" |
@@ -70,28 +71,29 @@ struct CMD { | |||
70 | }; | 71 | }; |
71 | 72 | ||
72 | const struct CMD cmds[] = { | 73 | const struct CMD cmds[] = { |
73 | { "CD", I_CHDIR }, | 74 | { "cd", I_CHDIR }, |
74 | { "CHDIR", I_CHDIR }, | 75 | { "chdir", I_CHDIR }, |
75 | { "CHGRP", I_CHGRP }, | 76 | { "chgrp", I_CHGRP }, |
76 | { "CHMOD", I_CHMOD }, | 77 | { "chmod", I_CHMOD }, |
77 | { "CHOWN", I_CHOWN }, | 78 | { "chown", I_CHOWN }, |
78 | { "EXIT", I_QUIT }, | 79 | { "dir", I_LS }, |
79 | { "GET", I_GET }, | 80 | { "exit", I_QUIT }, |
80 | { "HELP", I_HELP }, | 81 | { "get", I_GET }, |
81 | { "LCD", I_LCHDIR }, | 82 | { "help", I_HELP }, |
82 | { "LCHDIR", I_LCHDIR }, | 83 | { "lcd", I_LCHDIR }, |
83 | { "LLS", I_LLS }, | 84 | { "lchdir", I_LCHDIR }, |
84 | { "LMKDIR", I_LMKDIR }, | 85 | { "lls", I_LLS }, |
85 | { "LPWD", I_LPWD }, | 86 | { "lmkdir", I_LMKDIR }, |
86 | { "LS", I_LS }, | 87 | { "lpwd", I_LPWD }, |
87 | { "LUMASK", I_LUMASK }, | 88 | { "ls", I_LS }, |
88 | { "MKDIR", I_MKDIR }, | 89 | { "lumask", I_LUMASK }, |
89 | { "PUT", I_PUT }, | 90 | { "mkdir", I_MKDIR }, |
90 | { "PWD", I_PWD }, | 91 | { "put", I_PUT }, |
91 | { "QUIT", I_QUIT }, | 92 | { "pwd", I_PWD }, |
92 | { "RENAME", I_RENAME }, | 93 | { "quit", I_QUIT }, |
93 | { "RM", I_RM }, | 94 | { "rename", I_RENAME }, |
94 | { "RMDIR", I_RMDIR }, | 95 | { "rm", I_RM }, |
96 | { "rmdir", I_RMDIR }, | ||
95 | { "!", I_SHELL }, | 97 | { "!", I_SHELL }, |
96 | { "?", I_HELP }, | 98 | { "?", I_HELP }, |
97 | { NULL, -1} | 99 | { NULL, -1} |
@@ -101,28 +103,29 @@ void | |||
101 | help(void) | 103 | help(void) |
102 | { | 104 | { |
103 | printf("Available commands:\n"); | 105 | printf("Available commands:\n"); |
104 | printf("CD path Change remote directory to 'path'\n"); | 106 | printf("cd path Change remote directory to 'path'\n"); |
105 | printf("LCD path Change local directory to 'path'\n"); | 107 | printf("lcd path Change local directory to 'path'\n"); |
106 | printf("CHGRP grp path Change group of file 'path' to 'grp'\n"); | 108 | printf("chgrp grp path Change group of file 'path' to 'grp'\n"); |
107 | printf("CHMOD mode path Change permissions of file 'path' to 'mode'\n"); | 109 | printf("chmod mode path Change permissions of file 'path' to 'mode'\n"); |
108 | printf("CHOWN own path Change owner of file 'path' to 'own'\n"); | 110 | printf("chown own path Change owner of file 'path' to 'own'\n"); |
109 | printf("HELP Display this help text\n"); | 111 | printf("help Display this help text\n"); |
110 | printf("GET remote-path [local-path] Download file\n"); | 112 | printf("get remote-path [local-path] Download file\n"); |
111 | printf("LLS [ls options] [path] Display local directory listing\n"); | 113 | printf("lls [ls-options [path]] Display local directory listing\n"); |
112 | printf("LMKDIR path Create local directory\n"); | 114 | printf("lmkdir path Create local directory\n"); |
113 | printf("LPWD Print local working directory\n"); | 115 | printf("lpwd Print local working directory\n"); |
114 | printf("LS [path] Display remote directory listing\n"); | 116 | printf("ls [path] Display remote directory listing\n"); |
115 | printf("LUMASK umask Set local umask to 'umask'\n"); | 117 | printf("lumask umask Set local umask to 'umask'\n"); |
116 | printf("MKDIR path Create remote directory\n"); | 118 | printf("mkdir path Create remote directory\n"); |
117 | printf("PUT local-path [remote-path] Upload file\n"); | 119 | printf("put local-path [remote-path] Upload file\n"); |
118 | printf("PWD Display remote working directory\n"); | 120 | printf("pwd Display remote working directory\n"); |
119 | printf("EXIT Quit sftp\n"); | 121 | printf("exit Quit sftp\n"); |
120 | printf("QUIT Quit sftp\n"); | 122 | printf("quit Quit sftp\n"); |
121 | printf("RENAME oldpath newpath Rename remote file\n"); | 123 | printf("rename oldpath newpath Rename remote file\n"); |
122 | printf("RMDIR path Remove remote directory\n"); | 124 | printf("rmdir path Remove remote directory\n"); |
123 | printf("RM path Delete remote file\n"); | 125 | printf("rm path Delete remote file\n"); |
124 | printf("!command Execute 'command' in local shell\n"); | 126 | printf("!command Execute 'command' in local shell\n"); |
125 | printf("! Escape to local shell\n"); | 127 | printf("! Escape to local shell\n"); |
128 | printf("? Synonym for help\n"); | ||
126 | } | 129 | } |
127 | 130 | ||
128 | void | 131 | void |
@@ -166,13 +169,15 @@ void | |||
166 | local_do_ls(const char *args) | 169 | local_do_ls(const char *args) |
167 | { | 170 | { |
168 | if (!args || !*args) | 171 | if (!args || !*args) |
169 | local_do_shell("ls"); | 172 | local_do_shell(_PATH_LS); |
170 | else { | 173 | else { |
171 | char *buf = xmalloc(8 + strlen(args) + 1); | 174 | int len = strlen(_PATH_LS " ") + strlen(args) + 1; |
175 | char *buf = xmalloc(len); | ||
172 | 176 | ||
173 | /* XXX: quoting - rip quoting code from ftp? */ | 177 | /* XXX: quoting - rip quoting code from ftp? */ |
174 | sprintf(buf, "/bin/ls %s", args); | 178 | snprintf(buf, len, _PATH_LS " %s", args); |
175 | local_do_shell(buf); | 179 | local_do_shell(buf); |
180 | xfree(buf); | ||
176 | } | 181 | } |
177 | } | 182 | } |
178 | 183 | ||
@@ -198,7 +203,7 @@ parse_getput_flags(const char **cpp, int *pflag) | |||
198 | 203 | ||
199 | /* Check for flags */ | 204 | /* Check for flags */ |
200 | if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) { | 205 | if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) { |
201 | switch (*cp) { | 206 | switch (cp[1]) { |
202 | case 'P': | 207 | case 'P': |
203 | *pflag = 1; | 208 | *pflag = 1; |
204 | break; | 209 | break; |
@@ -216,50 +221,49 @@ parse_getput_flags(const char **cpp, int *pflag) | |||
216 | int | 221 | int |
217 | get_pathname(const char **cpp, char **path) | 222 | get_pathname(const char **cpp, char **path) |
218 | { | 223 | { |
219 | const char *quot, *cp = *cpp; | 224 | const char *cp = *cpp, *end; |
225 | char quot; | ||
220 | int i; | 226 | int i; |
221 | 227 | ||
222 | cp += strspn(cp, WHITESPACE); | 228 | cp += strspn(cp, WHITESPACE); |
223 | if (!*cp) { | 229 | if (!*cp) { |
224 | *cpp = cp; | 230 | *cpp = cp; |
225 | *path = NULL; | 231 | *path = NULL; |
226 | return(0); | 232 | return (0); |
227 | } | 233 | } |
228 | 234 | ||
229 | /* Check for quoted filenames */ | 235 | /* Check for quoted filenames */ |
230 | if (*cp == '\"' || *cp == '\'') { | 236 | if (*cp == '\"' || *cp == '\'') { |
231 | quot = cp++; | 237 | quot = *cp++; |
232 | for(i = 0; cp[i] && cp[i] != *quot; i++) | 238 | |
233 | ; | 239 | end = strchr(cp, quot); |
234 | if (!cp[i]) { | 240 | if (end == NULL) { |
235 | error("Unterminated quote"); | 241 | error("Unterminated quote"); |
236 | *path = NULL; | 242 | goto fail; |
237 | return(-1); | ||
238 | } | 243 | } |
239 | if (i == 0) { | 244 | if (cp == end) { |
240 | error("Empty quotes"); | 245 | error("Empty quotes"); |
241 | *path = NULL; | 246 | goto fail; |
242 | return(-1); | ||
243 | } | 247 | } |
244 | *path = xmalloc(i + 1); | 248 | *cpp = end + 1 + strspn(end + 1, WHITESPACE); |
245 | memcpy(*path, cp, i); | 249 | } else { |
246 | (*path)[i] = '\0'; | 250 | /* Read to end of filename */ |
247 | cp += i + 1; | 251 | end = strpbrk(cp, WHITESPACE); |
248 | *cpp = cp + strspn(cp, WHITESPACE); | 252 | if (end == NULL) |
249 | return(0); | 253 | end = strchr(cp, '\0'); |
254 | *cpp = end + strspn(end, WHITESPACE); | ||
250 | } | 255 | } |
251 | 256 | ||
252 | /* Read to end of filename */ | 257 | i = end - cp; |
253 | for(i = 0; cp[i] && cp[i] != ' '; i++) | ||
254 | ; | ||
255 | 258 | ||
256 | *path = xmalloc(i + 1); | 259 | *path = xmalloc(i + 1); |
257 | memcpy(*path, cp, i); | 260 | memcpy(*path, cp, i); |
258 | (*path)[i] = '\0'; | 261 | (*path)[i] = '\0'; |
259 | cp += i; | ||
260 | *cpp = cp + strspn(cp, WHITESPACE); | ||
261 | |||
262 | return(0); | 262 | return(0); |
263 | |||
264 | fail: | ||
265 | *path = NULL; | ||
266 | return (-1); | ||
263 | } | 267 | } |
264 | 268 | ||
265 | int | 269 | int |
@@ -270,7 +274,6 @@ infer_path(const char *p, char **ifp) | |||
270 | debug("XXX: P = \"%s\"", p); | 274 | debug("XXX: P = \"%s\"", p); |
271 | 275 | ||
272 | cp = strrchr(p, '/'); | 276 | cp = strrchr(p, '/'); |
273 | |||
274 | if (cp == NULL) { | 277 | if (cp == NULL) { |
275 | *ifp = xstrdup(p); | 278 | *ifp = xstrdup(p); |
276 | return(0); | 279 | return(0); |
@@ -421,14 +424,13 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg, | |||
421 | } | 424 | } |
422 | 425 | ||
423 | *cpp = cp; | 426 | *cpp = cp; |
424 | |||
425 | return(cmdnum); | 427 | return(cmdnum); |
426 | } | 428 | } |
427 | 429 | ||
428 | int | 430 | int |
429 | parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | 431 | parse_dispatch_command(int in, int out, const char *cmd, char **pwd) |
430 | { | 432 | { |
431 | char *path1, *path2; | 433 | char *path1, *path2, *tmp; |
432 | int pflag, cmdnum; | 434 | int pflag, cmdnum; |
433 | unsigned long n_arg; | 435 | unsigned long n_arg; |
434 | Attrib a, *aa; | 436 | Attrib a, *aa; |
@@ -471,12 +473,44 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
471 | break; | 473 | break; |
472 | case I_CHDIR: | 474 | case I_CHDIR: |
473 | path1 = make_absolute(path1, *pwd); | 475 | path1 = make_absolute(path1, *pwd); |
476 | if ((tmp = do_realpath(in, out, path1)) == NULL) | ||
477 | break; | ||
478 | if ((aa = do_stat(in, out, tmp)) == NULL) { | ||
479 | xfree(tmp); | ||
480 | break; | ||
481 | } | ||
482 | if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { | ||
483 | error("Can't change directory: Can't check target"); | ||
484 | xfree(tmp); | ||
485 | break; | ||
486 | } | ||
487 | if (!S_ISDIR(aa->perm)) { | ||
488 | error("Can't change directory: \"%s\" is not " | ||
489 | "a directory", tmp); | ||
490 | xfree(tmp); | ||
491 | break; | ||
492 | } | ||
474 | xfree(*pwd); | 493 | xfree(*pwd); |
475 | *pwd = do_realpath(in, out, path1); | 494 | *pwd = tmp; |
476 | break; | 495 | break; |
477 | case I_LS: | 496 | case I_LS: |
497 | if (!path1) { | ||
498 | do_ls(in, out, *pwd); | ||
499 | break; | ||
500 | } | ||
478 | path1 = make_absolute(path1, *pwd); | 501 | path1 = make_absolute(path1, *pwd); |
479 | do_ls(in, out, path1?path1:*pwd); | 502 | if ((tmp = do_realpath(in, out, path1)) == NULL) |
503 | break; | ||
504 | xfree(path1); | ||
505 | path1 = tmp; | ||
506 | if ((aa = do_stat(in, out, path1)) == NULL) | ||
507 | break; | ||
508 | if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && | ||
509 | !S_ISDIR(aa->perm)) { | ||
510 | error("Can't ls: \"%s\" is not a directory", path1); | ||
511 | break; | ||
512 | } | ||
513 | do_ls(in, out, path1); | ||
480 | break; | 514 | break; |
481 | case I_LCHDIR: | 515 | case I_LCHDIR: |
482 | if (chdir(path1) == -1) | 516 | if (chdir(path1) == -1) |
@@ -485,7 +519,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
485 | break; | 519 | break; |
486 | case I_LMKDIR: | 520 | case I_LMKDIR: |
487 | if (mkdir(path1, 0777) == -1) | 521 | if (mkdir(path1, 0777) == -1) |
488 | error("Couldn't create local directory to " | 522 | error("Couldn't create local directory " |
489 | "\"%s\": %s", path1, strerror(errno)); | 523 | "\"%s\": %s", path1, strerror(errno)); |
490 | break; | 524 | break; |
491 | case I_LLS: | 525 | case I_LLS: |
@@ -506,23 +540,27 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
506 | break; | 540 | break; |
507 | case I_CHOWN: | 541 | case I_CHOWN: |
508 | path1 = make_absolute(path1, *pwd); | 542 | path1 = make_absolute(path1, *pwd); |
509 | aa = do_stat(in, out, path1); | 543 | if (!(aa = do_stat(in, out, path1))) |
544 | break; | ||
510 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 545 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
511 | error("Can't get current ownership of " | 546 | error("Can't get current ownership of " |
512 | "remote file \"%s\"", path1); | 547 | "remote file \"%s\"", path1); |
513 | break; | 548 | break; |
514 | } | 549 | } |
550 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; | ||
515 | aa->uid = n_arg; | 551 | aa->uid = n_arg; |
516 | do_setstat(in, out, path1, aa); | 552 | do_setstat(in, out, path1, aa); |
517 | break; | 553 | break; |
518 | case I_CHGRP: | 554 | case I_CHGRP: |
519 | path1 = make_absolute(path1, *pwd); | 555 | path1 = make_absolute(path1, *pwd); |
520 | aa = do_stat(in, out, path1); | 556 | if (!(aa = do_stat(in, out, path1))) |
557 | break; | ||
521 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 558 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
522 | error("Can't get current ownership of " | 559 | error("Can't get current ownership of " |
523 | "remote file \"%s\"", path1); | 560 | "remote file \"%s\"", path1); |
524 | break; | 561 | break; |
525 | } | 562 | } |
563 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; | ||
526 | aa->gid = n_arg; | 564 | aa->gid = n_arg; |
527 | do_setstat(in, out, path1, aa); | 565 | do_setstat(in, out, path1, aa); |
528 | break; | 566 | break; |
@@ -550,7 +588,6 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
550 | xfree(path1); | 588 | xfree(path1); |
551 | if (path2) | 589 | if (path2) |
552 | xfree(path2); | 590 | xfree(path2); |
553 | |||
554 | return(0); | 591 | return(0); |
555 | } | 592 | } |
556 | 593 | ||
@@ -564,8 +601,8 @@ interactive_loop(int fd_in, int fd_out) | |||
564 | if (pwd == NULL) | 601 | if (pwd == NULL) |
565 | fatal("Need cwd"); | 602 | fatal("Need cwd"); |
566 | 603 | ||
567 | setvbuf(stdout, (char *)NULL, _IOLBF, 0); | 604 | setvbuf(stdout, NULL, _IOLBF, 0); |
568 | setvbuf(stdin, (char *)NULL, _IOLBF, 0); | 605 | setvbuf(stdin, NULL, _IOLBF, 0); |
569 | 606 | ||
570 | for(;;) { | 607 | for(;;) { |
571 | char *cp; | 608 | char *cp; |