diff options
author | Colin Watson <cjwatson@debian.org> | 2019-06-05 06:41:44 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2019-06-09 22:09:07 +0100 |
commit | 865a97e05b6aab1619e1c8eeb33ccb8f9a9e48d3 (patch) | |
tree | 7bb2128eb663180bacfabca88f26d26bf0733824 /sftp.c | |
parent | ba627ba172d6649919baedff5ba2789610da382a (diff) | |
parent | 7d50f9e5be88179325983a1f58c9d51bb58f025a (diff) |
New upstream release (8.0p1)
Diffstat (limited to 'sftp.c')
-rw-r--r-- | sftp.c | 118 |
1 files changed, 76 insertions, 42 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp.c,v 1.186 2018/09/07 04:26:56 dtucker Exp $ */ | 1 | /* $OpenBSD: sftp.c,v 1.190 2019/01/21 22:50:42 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -278,9 +278,9 @@ help(void) | |||
278 | printf("Available commands:\n" | 278 | printf("Available commands:\n" |
279 | "bye Quit sftp\n" | 279 | "bye Quit sftp\n" |
280 | "cd path Change remote directory to 'path'\n" | 280 | "cd path Change remote directory to 'path'\n" |
281 | "chgrp grp path Change group of file 'path' to 'grp'\n" | 281 | "chgrp [-h] grp path Change group of file 'path' to 'grp'\n" |
282 | "chmod mode path Change permissions of file 'path' to 'mode'\n" | 282 | "chmod [-h] mode path Change permissions of file 'path' to 'mode'\n" |
283 | "chown own path Change owner of file 'path' to 'own'\n" | 283 | "chown [-h] own path Change owner of file 'path' to 'own'\n" |
284 | "df [-hi] [path] Display statistics for current directory or\n" | 284 | "df [-hi] [path] Display statistics for current directory or\n" |
285 | " filesystem containing 'path'\n" | 285 | " filesystem containing 'path'\n" |
286 | "exit Quit sftp\n" | 286 | "exit Quit sftp\n" |
@@ -389,7 +389,7 @@ make_absolute(char *p, const char *pwd) | |||
389 | char *abs_str; | 389 | char *abs_str; |
390 | 390 | ||
391 | /* Derelativise */ | 391 | /* Derelativise */ |
392 | if (p && p[0] != '/') { | 392 | if (p && !path_absolute(p)) { |
393 | abs_str = path_append(pwd, p); | 393 | abs_str = path_append(pwd, p); |
394 | free(p); | 394 | free(p); |
395 | return(abs_str); | 395 | return(abs_str); |
@@ -562,6 +562,30 @@ parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag) | |||
562 | } | 562 | } |
563 | 563 | ||
564 | static int | 564 | static int |
565 | parse_ch_flags(const char *cmd, char **argv, int argc, int *hflag) | ||
566 | { | ||
567 | extern int opterr, optind, optopt, optreset; | ||
568 | int ch; | ||
569 | |||
570 | optind = optreset = 1; | ||
571 | opterr = 0; | ||
572 | |||
573 | *hflag = 0; | ||
574 | while ((ch = getopt(argc, argv, "h")) != -1) { | ||
575 | switch (ch) { | ||
576 | case 'h': | ||
577 | *hflag = 1; | ||
578 | break; | ||
579 | default: | ||
580 | error("%s: Invalid flag -%c", cmd, optopt); | ||
581 | return -1; | ||
582 | } | ||
583 | } | ||
584 | |||
585 | return optind; | ||
586 | } | ||
587 | |||
588 | static int | ||
565 | parse_no_flags(const char *cmd, char **argv, int argc) | 589 | parse_no_flags(const char *cmd, char **argv, int argc) |
566 | { | 590 | { |
567 | extern int opterr, optind, optopt, optreset; | 591 | extern int opterr, optind, optopt, optreset; |
@@ -1296,7 +1320,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, | |||
1296 | } | 1320 | } |
1297 | 1321 | ||
1298 | static int | 1322 | static int |
1299 | parse_args(const char **cpp, int *ignore_errors, int *aflag, | 1323 | parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag, |
1300 | int *fflag, int *hflag, int *iflag, int *lflag, int *pflag, | 1324 | int *fflag, int *hflag, int *iflag, int *lflag, int *pflag, |
1301 | int *rflag, int *sflag, | 1325 | int *rflag, int *sflag, |
1302 | unsigned long *n_arg, char **path1, char **path2) | 1326 | unsigned long *n_arg, char **path1, char **path2) |
@@ -1310,13 +1334,23 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, | |||
1310 | /* Skip leading whitespace */ | 1334 | /* Skip leading whitespace */ |
1311 | cp = cp + strspn(cp, WHITESPACE); | 1335 | cp = cp + strspn(cp, WHITESPACE); |
1312 | 1336 | ||
1313 | /* Check for leading '-' (disable error processing) */ | 1337 | /* |
1338 | * Check for leading '-' (disable error processing) and '@' (suppress | ||
1339 | * command echo) | ||
1340 | */ | ||
1314 | *ignore_errors = 0; | 1341 | *ignore_errors = 0; |
1315 | if (*cp == '-') { | 1342 | *disable_echo = 0; |
1316 | *ignore_errors = 1; | 1343 | for (;*cp != '\0'; cp++) { |
1317 | cp++; | 1344 | if (*cp == '-') { |
1318 | cp = cp + strspn(cp, WHITESPACE); | 1345 | *ignore_errors = 1; |
1346 | } else if (*cp == '@') { | ||
1347 | *disable_echo = 1; | ||
1348 | } else { | ||
1349 | /* all other characters terminate prefix processing */ | ||
1350 | break; | ||
1351 | } | ||
1319 | } | 1352 | } |
1353 | cp = cp + strspn(cp, WHITESPACE); | ||
1320 | 1354 | ||
1321 | /* Ignore blank lines and lines which begin with comment '#' char */ | 1355 | /* Ignore blank lines and lines which begin with comment '#' char */ |
1322 | if (*cp == '\0' || *cp == '#') | 1356 | if (*cp == '\0' || *cp == '#') |
@@ -1446,7 +1480,7 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, | |||
1446 | /* FALLTHROUGH */ | 1480 | /* FALLTHROUGH */ |
1447 | case I_CHOWN: | 1481 | case I_CHOWN: |
1448 | case I_CHGRP: | 1482 | case I_CHGRP: |
1449 | if ((optidx = parse_no_flags(cmd, argv, argc)) == -1) | 1483 | if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1) |
1450 | return -1; | 1484 | return -1; |
1451 | /* Get numeric arg (mandatory) */ | 1485 | /* Get numeric arg (mandatory) */ |
1452 | if (argc - optidx < 1) | 1486 | if (argc - optidx < 1) |
@@ -1491,11 +1525,12 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, | |||
1491 | 1525 | ||
1492 | static int | 1526 | static int |
1493 | parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | 1527 | parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, |
1494 | const char *startdir, int err_abort) | 1528 | const char *startdir, int err_abort, int echo_command) |
1495 | { | 1529 | { |
1530 | const char *ocmd = cmd; | ||
1496 | char *path1, *path2, *tmp; | 1531 | char *path1, *path2, *tmp; |
1497 | int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, | 1532 | int ignore_errors = 0, disable_echo = 1; |
1498 | iflag = 0; | 1533 | int aflag = 0, fflag = 0, hflag = 0, iflag = 0; |
1499 | int lflag = 0, pflag = 0, rflag = 0, sflag = 0; | 1534 | int lflag = 0, pflag = 0, rflag = 0, sflag = 0; |
1500 | int cmdnum, i; | 1535 | int cmdnum, i; |
1501 | unsigned long n_arg = 0; | 1536 | unsigned long n_arg = 0; |
@@ -1505,11 +1540,15 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1505 | glob_t g; | 1540 | glob_t g; |
1506 | 1541 | ||
1507 | path1 = path2 = NULL; | 1542 | path1 = path2 = NULL; |
1508 | cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag, | 1543 | cmdnum = parse_args(&cmd, &ignore_errors, &disable_echo, &aflag, &fflag, |
1509 | &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2); | 1544 | &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, |
1545 | &path1, &path2); | ||
1510 | if (ignore_errors != 0) | 1546 | if (ignore_errors != 0) |
1511 | err_abort = 0; | 1547 | err_abort = 0; |
1512 | 1548 | ||
1549 | if (echo_command && !disable_echo) | ||
1550 | mprintf("sftp> %s\n", ocmd); | ||
1551 | |||
1513 | memset(&g, 0, sizeof(g)); | 1552 | memset(&g, 0, sizeof(g)); |
1514 | 1553 | ||
1515 | /* Perform command */ | 1554 | /* Perform command */ |
@@ -1608,7 +1647,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1608 | 1647 | ||
1609 | /* Strip pwd off beginning of non-absolute paths */ | 1648 | /* Strip pwd off beginning of non-absolute paths */ |
1610 | tmp = NULL; | 1649 | tmp = NULL; |
1611 | if (*path1 != '/') | 1650 | if (!path_absolute(path1)) |
1612 | tmp = *pwd; | 1651 | tmp = *pwd; |
1613 | 1652 | ||
1614 | path1 = make_absolute(path1, *pwd); | 1653 | path1 = make_absolute(path1, *pwd); |
@@ -1660,7 +1699,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1660 | if (!quiet) | 1699 | if (!quiet) |
1661 | mprintf("Changing mode on %s\n", | 1700 | mprintf("Changing mode on %s\n", |
1662 | g.gl_pathv[i]); | 1701 | g.gl_pathv[i]); |
1663 | err = do_setstat(conn, g.gl_pathv[i], &a); | 1702 | err = (hflag ? do_lsetstat : do_setstat)(conn, |
1703 | g.gl_pathv[i], &a); | ||
1664 | if (err != 0 && err_abort) | 1704 | if (err != 0 && err_abort) |
1665 | break; | 1705 | break; |
1666 | } | 1706 | } |
@@ -1670,7 +1710,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1670 | path1 = make_absolute(path1, *pwd); | 1710 | path1 = make_absolute(path1, *pwd); |
1671 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); | 1711 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
1672 | for (i = 0; g.gl_pathv[i] && !interrupted; i++) { | 1712 | for (i = 0; g.gl_pathv[i] && !interrupted; i++) { |
1673 | if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { | 1713 | if (!(aa = (hflag ? do_lstat : do_stat)(conn, |
1714 | g.gl_pathv[i], 0))) { | ||
1674 | if (err_abort) { | 1715 | if (err_abort) { |
1675 | err = -1; | 1716 | err = -1; |
1676 | break; | 1717 | break; |
@@ -1698,7 +1739,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1698 | g.gl_pathv[i]); | 1739 | g.gl_pathv[i]); |
1699 | aa->gid = n_arg; | 1740 | aa->gid = n_arg; |
1700 | } | 1741 | } |
1701 | err = do_setstat(conn, g.gl_pathv[i], aa); | 1742 | err = (hflag ? do_lsetstat : do_setstat)(conn, |
1743 | g.gl_pathv[i], aa); | ||
1702 | if (err != 0 && err_abort) | 1744 | if (err != 0 && err_abort) |
1703 | break; | 1745 | break; |
1704 | } | 1746 | } |
@@ -1936,7 +1978,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, | |||
1936 | xasprintf(&tmp, "%s*", file); | 1978 | xasprintf(&tmp, "%s*", file); |
1937 | 1979 | ||
1938 | /* Check if the path is absolute. */ | 1980 | /* Check if the path is absolute. */ |
1939 | isabs = tmp[0] == '/'; | 1981 | isabs = path_absolute(tmp); |
1940 | 1982 | ||
1941 | memset(&g, 0, sizeof(g)); | 1983 | memset(&g, 0, sizeof(g)); |
1942 | if (remote != LOCAL) { | 1984 | if (remote != LOCAL) { |
@@ -2169,7 +2211,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) | |||
2169 | mprintf("Changing to: %s\n", dir); | 2211 | mprintf("Changing to: %s\n", dir); |
2170 | snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); | 2212 | snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); |
2171 | if (parse_dispatch_command(conn, cmd, | 2213 | if (parse_dispatch_command(conn, cmd, |
2172 | &remote_path, startdir, 1) != 0) { | 2214 | &remote_path, startdir, 1, 0) != 0) { |
2173 | free(dir); | 2215 | free(dir); |
2174 | free(startdir); | 2216 | free(startdir); |
2175 | free(remote_path); | 2217 | free(remote_path); |
@@ -2183,7 +2225,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) | |||
2183 | file2 == NULL ? "" : " ", | 2225 | file2 == NULL ? "" : " ", |
2184 | file2 == NULL ? "" : file2); | 2226 | file2 == NULL ? "" : file2); |
2185 | err = parse_dispatch_command(conn, cmd, | 2227 | err = parse_dispatch_command(conn, cmd, |
2186 | &remote_path, startdir, 1); | 2228 | &remote_path, startdir, 1, 0); |
2187 | free(dir); | 2229 | free(dir); |
2188 | free(startdir); | 2230 | free(startdir); |
2189 | free(remote_path); | 2231 | free(remote_path); |
@@ -2199,8 +2241,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) | |||
2199 | interactive = !batchmode && isatty(STDIN_FILENO); | 2241 | interactive = !batchmode && isatty(STDIN_FILENO); |
2200 | err = 0; | 2242 | err = 0; |
2201 | for (;;) { | 2243 | for (;;) { |
2202 | char *cp; | ||
2203 | |||
2204 | signal(SIGINT, SIG_IGN); | 2244 | signal(SIGINT, SIG_IGN); |
2205 | 2245 | ||
2206 | if (el == NULL) { | 2246 | if (el == NULL) { |
@@ -2211,12 +2251,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) | |||
2211 | printf("\n"); | 2251 | printf("\n"); |
2212 | break; | 2252 | break; |
2213 | } | 2253 | } |
2214 | if (!interactive) { /* Echo command */ | ||
2215 | mprintf("sftp> %s", cmd); | ||
2216 | if (strlen(cmd) > 0 && | ||
2217 | cmd[strlen(cmd) - 1] != '\n') | ||
2218 | printf("\n"); | ||
2219 | } | ||
2220 | } else { | 2254 | } else { |
2221 | #ifdef USE_LIBEDIT | 2255 | #ifdef USE_LIBEDIT |
2222 | const char *line; | 2256 | const char *line; |
@@ -2235,16 +2269,14 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) | |||
2235 | #endif /* USE_LIBEDIT */ | 2269 | #endif /* USE_LIBEDIT */ |
2236 | } | 2270 | } |
2237 | 2271 | ||
2238 | cp = strrchr(cmd, '\n'); | 2272 | cmd[strcspn(cmd, "\n")] = '\0'; |
2239 | if (cp) | ||
2240 | *cp = '\0'; | ||
2241 | 2273 | ||
2242 | /* Handle user interrupts gracefully during commands */ | 2274 | /* Handle user interrupts gracefully during commands */ |
2243 | interrupted = 0; | 2275 | interrupted = 0; |
2244 | signal(SIGINT, cmd_interrupt); | 2276 | signal(SIGINT, cmd_interrupt); |
2245 | 2277 | ||
2246 | err = parse_dispatch_command(conn, cmd, &remote_path, | 2278 | err = parse_dispatch_command(conn, cmd, &remote_path, |
2247 | startdir, batchmode); | 2279 | startdir, batchmode, !interactive && el == NULL); |
2248 | if (err != 0) | 2280 | if (err != 0) |
2249 | break; | 2281 | break; |
2250 | } | 2282 | } |
@@ -2330,11 +2362,10 @@ usage(void) | |||
2330 | 2362 | ||
2331 | fprintf(stderr, | 2363 | fprintf(stderr, |
2332 | "usage: %s [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" | 2364 | "usage: %s [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" |
2333 | " [-D sftp_server_path] [-F ssh_config] " | 2365 | " [-D sftp_server_path] [-F ssh_config] [-i identity_file]\n" |
2334 | "[-i identity_file] [-l limit]\n" | 2366 | " [-J destination] [-l limit] [-o ssh_option] [-P port]\n" |
2335 | " [-o ssh_option] [-P port] [-R num_requests] " | 2367 | " [-R num_requests] [-S program] [-s subsystem | sftp_server]\n" |
2336 | "[-S program]\n" | 2368 | " destination\n", |
2337 | " [-s subsystem | sftp_server] destination\n", | ||
2338 | __progname); | 2369 | __progname); |
2339 | exit(1); | 2370 | exit(1); |
2340 | } | 2371 | } |
@@ -2362,6 +2393,8 @@ main(int argc, char **argv) | |||
2362 | sanitise_stdfd(); | 2393 | sanitise_stdfd(); |
2363 | msetlocale(); | 2394 | msetlocale(); |
2364 | 2395 | ||
2396 | seed_rng(); | ||
2397 | |||
2365 | __progname = ssh_get_progname(argv[0]); | 2398 | __progname = ssh_get_progname(argv[0]); |
2366 | memset(&args, '\0', sizeof(args)); | 2399 | memset(&args, '\0', sizeof(args)); |
2367 | args.list = NULL; | 2400 | args.list = NULL; |
@@ -2375,7 +2408,7 @@ main(int argc, char **argv) | |||
2375 | infile = stdin; | 2408 | infile = stdin; |
2376 | 2409 | ||
2377 | while ((ch = getopt(argc, argv, | 2410 | while ((ch = getopt(argc, argv, |
2378 | "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { | 2411 | "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) { |
2379 | switch (ch) { | 2412 | switch (ch) { |
2380 | /* Passed through to ssh(1) */ | 2413 | /* Passed through to ssh(1) */ |
2381 | case '4': | 2414 | case '4': |
@@ -2385,6 +2418,7 @@ main(int argc, char **argv) | |||
2385 | break; | 2418 | break; |
2386 | /* Passed through to ssh(1) with argument */ | 2419 | /* Passed through to ssh(1) with argument */ |
2387 | case 'F': | 2420 | case 'F': |
2421 | case 'J': | ||
2388 | case 'c': | 2422 | case 'c': |
2389 | case 'i': | 2423 | case 'i': |
2390 | case 'o': | 2424 | case 'o': |