PageRenderTime 132ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/pscp.c

http://futty.codeplex.com
C | 2412 lines | 1781 code | 245 blank | 386 comment | 483 complexity | 7342e7ffc0435eed4f59bd3f904b3373 MD5 | raw file
  1. /*
  2. * scp.c - Scp (Secure Copy) client for PuTTY.
  3. * Joris van Rantwijk, Simon Tatham
  4. *
  5. * This is mainly based on ssh-1.2.26/scp.c by Timo Rinne & Tatu Ylonen.
  6. * They, in turn, used stuff from BSD rcp.
  7. *
  8. * (SGT, 2001-09-10: Joris van Rantwijk assures me that although
  9. * this file as originally submitted was inspired by, and
  10. * _structurally_ based on, ssh-1.2.26's scp.c, there wasn't any
  11. * actual code duplicated, so the above comment shouldn't give rise
  12. * to licensing issues.)
  13. */
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <limits.h>
  18. #include <time.h>
  19. #include <assert.h>
  20. #define PUTTY_DO_GLOBALS
  21. #include "putty.h"
  22. #include "psftp.h"
  23. #include "ssh.h"
  24. #include "sftp.h"
  25. #include "storage.h"
  26. #include "int64.h"
  27. static int list = 0;
  28. static int verbose = 0;
  29. static int recursive = 0;
  30. static int preserve = 0;
  31. static int targetshouldbedirectory = 0;
  32. static int statistics = 1;
  33. static int prev_stats_len = 0;
  34. static int scp_unsafe_mode = 0;
  35. static int errs = 0;
  36. static int try_scp = 1;
  37. static int try_sftp = 1;
  38. static int main_cmd_is_sftp = 0;
  39. static int fallback_cmd_is_sftp = 0;
  40. static int using_sftp = 0;
  41. static Backend *back;
  42. static void *backhandle;
  43. static Conf *conf;
  44. int sent_eof = FALSE;
  45. static void source(char *src);
  46. static void rsource(char *src);
  47. static void sink(char *targ, char *src);
  48. const char *const appname = "PSCP";
  49. /*
  50. * The maximum amount of queued data we accept before we stop and
  51. * wait for the server to process some.
  52. */
  53. #define MAX_SCP_BUFSIZE 16384
  54. void ldisc_send(void *handle, char *buf, int len, int interactive)
  55. {
  56. /*
  57. * This is only here because of the calls to ldisc_send(NULL,
  58. * 0) in ssh.c. Nothing in PSCP actually needs to use the ldisc
  59. * as an ldisc. So if we get called with any real data, I want
  60. * to know about it.
  61. */
  62. assert(len == 0);
  63. }
  64. static void tell_char(FILE * stream, char c)
  65. {
  66. fputc(c, stream);
  67. }
  68. static void tell_str(FILE * stream, char *str)
  69. {
  70. unsigned int i;
  71. for (i = 0; i < strlen(str); ++i)
  72. tell_char(stream, str[i]);
  73. }
  74. static void tell_user(FILE * stream, char *fmt, ...)
  75. {
  76. char *str, *str2;
  77. va_list ap;
  78. va_start(ap, fmt);
  79. str = dupvprintf(fmt, ap);
  80. va_end(ap);
  81. str2 = dupcat(str, "\n", NULL);
  82. sfree(str);
  83. tell_str(stream, str2);
  84. sfree(str2);
  85. }
  86. /*
  87. * Print an error message and perform a fatal exit.
  88. */
  89. void fatalbox(char *fmt, ...)
  90. {
  91. char *str, *str2;
  92. va_list ap;
  93. va_start(ap, fmt);
  94. str = dupvprintf(fmt, ap);
  95. str2 = dupcat("Fatal: ", str, "\n", NULL);
  96. sfree(str);
  97. va_end(ap);
  98. tell_str(stderr, str2);
  99. sfree(str2);
  100. errs++;
  101. cleanup_exit(1);
  102. }
  103. void modalfatalbox(char *fmt, ...)
  104. {
  105. char *str, *str2;
  106. va_list ap;
  107. va_start(ap, fmt);
  108. str = dupvprintf(fmt, ap);
  109. str2 = dupcat("Fatal: ", str, "\n", NULL);
  110. sfree(str);
  111. va_end(ap);
  112. tell_str(stderr, str2);
  113. sfree(str2);
  114. errs++;
  115. cleanup_exit(1);
  116. }
  117. void nonfatal(char *fmt, ...)
  118. {
  119. char *str, *str2;
  120. va_list ap;
  121. va_start(ap, fmt);
  122. str = dupvprintf(fmt, ap);
  123. str2 = dupcat("Error: ", str, "\n", NULL);
  124. sfree(str);
  125. va_end(ap);
  126. tell_str(stderr, str2);
  127. sfree(str2);
  128. errs++;
  129. }
  130. void connection_fatal(void *frontend, char *fmt, ...)
  131. {
  132. char *str, *str2;
  133. va_list ap;
  134. va_start(ap, fmt);
  135. str = dupvprintf(fmt, ap);
  136. str2 = dupcat("Fatal: ", str, "\n", NULL);
  137. sfree(str);
  138. va_end(ap);
  139. tell_str(stderr, str2);
  140. sfree(str2);
  141. errs++;
  142. cleanup_exit(1);
  143. }
  144. /*
  145. * In pscp, all agent requests should be synchronous, so this is a
  146. * never-called stub.
  147. */
  148. void agent_schedule_callback(void (*callback)(void *, void *, int),
  149. void *callback_ctx, void *data, int len)
  150. {
  151. assert(!"We shouldn't be here");
  152. }
  153. /*
  154. * Receive a block of data from the SSH link. Block until all data
  155. * is available.
  156. *
  157. * To do this, we repeatedly call the SSH protocol module, with our
  158. * own trap in from_backend() to catch the data that comes back. We
  159. * do this until we have enough data.
  160. */
  161. static unsigned char *outptr; /* where to put the data */
  162. static unsigned outlen; /* how much data required */
  163. static unsigned char *pending = NULL; /* any spare data */
  164. static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
  165. int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
  166. {
  167. unsigned char *p = (unsigned char *) data;
  168. unsigned len = (unsigned) datalen;
  169. /*
  170. * stderr data is just spouted to local stderr and otherwise
  171. * ignored.
  172. */
  173. if (is_stderr) {
  174. if (len > 0)
  175. if (fwrite(data, 1, len, stderr) < len)
  176. /* oh well */;
  177. return 0;
  178. }
  179. if ((outlen > 0) && (len > 0)) {
  180. unsigned used = outlen;
  181. if (used > len)
  182. used = len;
  183. memcpy(outptr, p, used);
  184. outptr += used;
  185. outlen -= used;
  186. p += used;
  187. len -= used;
  188. }
  189. if (len > 0) {
  190. if (pendsize < pendlen + len) {
  191. pendsize = pendlen + len + 4096;
  192. pending = sresize(pending, pendsize, unsigned char);
  193. }
  194. memcpy(pending + pendlen, p, len);
  195. pendlen += len;
  196. }
  197. return 0;
  198. }
  199. int from_backend_untrusted(void *frontend_handle, const char *data, int len)
  200. {
  201. /*
  202. * No "untrusted" output should get here (the way the code is
  203. * currently, it's all diverted by FLAG_STDERR).
  204. */
  205. assert(!"Unexpected call to from_backend_untrusted()");
  206. return 0; /* not reached */
  207. }
  208. int from_backend_eof(void *frontend)
  209. {
  210. /*
  211. * We expect to be the party deciding when to close the
  212. * connection, so if we see EOF before we sent it ourselves, we
  213. * should panic.
  214. */
  215. if (!sent_eof) {
  216. connection_fatal(frontend,
  217. "Received unexpected end-of-file from server");
  218. }
  219. return FALSE;
  220. }
  221. static int ssh_scp_recv(unsigned char *buf, int len)
  222. {
  223. outptr = buf;
  224. outlen = len;
  225. /*
  226. * See if the pending-input block contains some of what we
  227. * need.
  228. */
  229. if (pendlen > 0) {
  230. unsigned pendused = pendlen;
  231. if (pendused > outlen)
  232. pendused = outlen;
  233. memcpy(outptr, pending, pendused);
  234. memmove(pending, pending + pendused, pendlen - pendused);
  235. outptr += pendused;
  236. outlen -= pendused;
  237. pendlen -= pendused;
  238. if (pendlen == 0) {
  239. pendsize = 0;
  240. sfree(pending);
  241. pending = NULL;
  242. }
  243. if (outlen == 0)
  244. return len;
  245. }
  246. while (outlen > 0) {
  247. if (back->exitcode(backhandle) >= 0 || ssh_sftp_loop_iteration() < 0)
  248. return 0; /* doom */
  249. }
  250. return len;
  251. }
  252. /*
  253. * Loop through the ssh connection and authentication process.
  254. */
  255. static void ssh_scp_init(void)
  256. {
  257. while (!back->sendok(backhandle)) {
  258. if (back->exitcode(backhandle) >= 0) {
  259. errs++;
  260. return;
  261. }
  262. if (ssh_sftp_loop_iteration() < 0) {
  263. errs++;
  264. return; /* doom */
  265. }
  266. }
  267. /* Work out which backend we ended up using. */
  268. if (!ssh_fallback_cmd(backhandle))
  269. using_sftp = main_cmd_is_sftp;
  270. else
  271. using_sftp = fallback_cmd_is_sftp;
  272. if (verbose) {
  273. if (using_sftp)
  274. tell_user(stderr, "Using SFTP");
  275. else
  276. tell_user(stderr, "Using SCP1");
  277. }
  278. }
  279. /*
  280. * Print an error message and exit after closing the SSH link.
  281. */
  282. static void bump(char *fmt, ...)
  283. {
  284. char *str, *str2;
  285. va_list ap;
  286. va_start(ap, fmt);
  287. str = dupvprintf(fmt, ap);
  288. va_end(ap);
  289. str2 = dupcat(str, "\n", NULL);
  290. sfree(str);
  291. tell_str(stderr, str2);
  292. sfree(str2);
  293. errs++;
  294. if (back != NULL && back->connected(backhandle)) {
  295. char ch;
  296. back->special(backhandle, TS_EOF);
  297. sent_eof = TRUE;
  298. ssh_scp_recv((unsigned char *) &ch, 1);
  299. }
  300. cleanup_exit(1);
  301. }
  302. /*
  303. * Wait for the reply to a single SFTP request. Parallels the same
  304. * function in psftp.c (but isn't centralised into sftp.c because the
  305. * latter module handles SFTP only and shouldn't assume that SFTP is
  306. * the only thing going on by calling connection_fatal).
  307. */
  308. struct sftp_packet *sftp_wait_for_reply(struct sftp_request *req)
  309. {
  310. struct sftp_packet *pktin;
  311. struct sftp_request *rreq;
  312. sftp_register(req);
  313. pktin = sftp_recv();
  314. if (pktin == NULL)
  315. connection_fatal(NULL, "did not receive SFTP response packet "
  316. "from server");
  317. rreq = sftp_find_request(pktin);
  318. if (rreq != req)
  319. connection_fatal(NULL, "unable to understand SFTP response packet "
  320. "from server: %s", fxp_error());
  321. return pktin;
  322. }
  323. /*
  324. * Open an SSH connection to user@host and execute cmd.
  325. */
  326. static void do_cmd(char *host, char *user, char *cmd)
  327. {
  328. const char *err;
  329. char *realhost;
  330. void *logctx;
  331. if (host == NULL || host[0] == '\0')
  332. bump("Empty host name");
  333. /*
  334. * Remove fiddly bits of address: remove a colon suffix, and
  335. * the square brackets around an IPv6 literal address.
  336. */
  337. if (host[0] == '[') {
  338. host++;
  339. host[strcspn(host, "]")] = '\0';
  340. } else {
  341. host[strcspn(host, ":")] = '\0';
  342. }
  343. /*
  344. * If we haven't loaded session details already (e.g., from -load),
  345. * try looking for a session called "host".
  346. */
  347. if (!loaded_session) {
  348. /* Try to load settings for `host' into a temporary config */
  349. Conf *conf2 = conf_new();
  350. conf_set_str(conf2, CONF_host, "");
  351. do_defaults_then_file(host, conf2);
  352. if (conf_get_str(conf2, CONF_host)[0] != '\0') {
  353. /* Settings present and include hostname */
  354. /* Re-load data into the real config. */
  355. do_defaults(host, conf);
  356. } else {
  357. /* Session doesn't exist or mention a hostname. */
  358. /* Use `host' as a bare hostname. */
  359. conf_set_str(conf, CONF_host, host);
  360. }
  361. } else {
  362. /* Patch in hostname `host' to session details. */
  363. conf_set_str(conf, CONF_host, host);
  364. }
  365. /*
  366. * Force use of SSH. (If they got the protocol wrong we assume the
  367. * port is useless too.)
  368. */
  369. if (conf_get_int(conf, CONF_protocol) != PROT_SSH) {
  370. conf_set_int(conf, CONF_protocol, PROT_SSH);
  371. conf_set_int(conf, CONF_port, 22);
  372. }
  373. /*
  374. * Enact command-line overrides.
  375. */
  376. cmdline_run_saved(conf);
  377. /*
  378. * Muck about with the hostname in various ways.
  379. */
  380. {
  381. char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
  382. char *host = hostbuf;
  383. char *p, *q;
  384. /*
  385. * Trim leading whitespace.
  386. */
  387. host += strspn(host, " \t");
  388. /*
  389. * See if host is of the form user@host, and separate out
  390. * the username if so.
  391. */
  392. if (host[0] != '\0') {
  393. char *atsign = strrchr(host, '@');
  394. if (atsign) {
  395. *atsign = '\0';
  396. conf_set_str(conf, CONF_username, host);
  397. host = atsign + 1;
  398. }
  399. }
  400. /*
  401. * Remove any remaining whitespace.
  402. */
  403. p = hostbuf;
  404. q = host;
  405. while (*q) {
  406. if (*q != ' ' && *q != '\t')
  407. *p++ = *q;
  408. q++;
  409. }
  410. *p = '\0';
  411. conf_set_str(conf, CONF_host, hostbuf);
  412. sfree(hostbuf);
  413. }
  414. /* Set username */
  415. if (user != NULL && user[0] != '\0') {
  416. conf_set_str(conf, CONF_username, user);
  417. } else if (conf_get_str(conf, CONF_username)[0] == '\0') {
  418. user = get_username();
  419. if (!user)
  420. bump("Empty user name");
  421. else {
  422. if (verbose)
  423. tell_user(stderr, "Guessing user name: %s", user);
  424. conf_set_str(conf, CONF_username, user);
  425. sfree(user);
  426. }
  427. }
  428. /*
  429. * Disable scary things which shouldn't be enabled for simple
  430. * things like SCP and SFTP: agent forwarding, port forwarding,
  431. * X forwarding.
  432. */
  433. conf_set_int(conf, CONF_x11_forward, 0);
  434. conf_set_int(conf, CONF_agentfwd, 0);
  435. conf_set_int(conf, CONF_ssh_simple, TRUE);
  436. {
  437. char *key;
  438. while ((key = conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) != NULL)
  439. conf_del_str_str(conf, CONF_portfwd, key);
  440. }
  441. /*
  442. * Set up main and possibly fallback command depending on
  443. * options specified by user.
  444. * Attempt to start the SFTP subsystem as a first choice,
  445. * falling back to the provided scp command if that fails.
  446. */
  447. conf_set_str(conf, CONF_remote_cmd2, "");
  448. if (try_sftp) {
  449. /* First choice is SFTP subsystem. */
  450. main_cmd_is_sftp = 1;
  451. conf_set_str(conf, CONF_remote_cmd, "sftp");
  452. conf_set_int(conf, CONF_ssh_subsys, TRUE);
  453. if (try_scp) {
  454. /* Fallback is to use the provided scp command. */
  455. fallback_cmd_is_sftp = 0;
  456. conf_set_str(conf, CONF_remote_cmd2, cmd);
  457. conf_set_int(conf, CONF_ssh_subsys2, FALSE);
  458. } else {
  459. /* Since we're not going to try SCP, we may as well try
  460. * harder to find an SFTP server, since in the current
  461. * implementation we have a spare slot. */
  462. fallback_cmd_is_sftp = 1;
  463. /* see psftp.c for full explanation of this kludge */
  464. conf_set_str(conf, CONF_remote_cmd2,
  465. "test -x /usr/lib/sftp-server &&"
  466. " exec /usr/lib/sftp-server\n"
  467. "test -x /usr/local/lib/sftp-server &&"
  468. " exec /usr/local/lib/sftp-server\n"
  469. "exec sftp-server");
  470. conf_set_int(conf, CONF_ssh_subsys2, FALSE);
  471. }
  472. } else {
  473. /* Don't try SFTP at all; just try the scp command. */
  474. main_cmd_is_sftp = 0;
  475. conf_set_str(conf, CONF_remote_cmd, cmd);
  476. conf_set_int(conf, CONF_ssh_subsys, FALSE);
  477. }
  478. conf_set_int(conf, CONF_nopty, TRUE);
  479. back = &ssh_backend;
  480. err = back->init(NULL, &backhandle, conf,
  481. conf_get_str(conf, CONF_host),
  482. conf_get_int(conf, CONF_port),
  483. &realhost, 0,
  484. conf_get_int(conf, CONF_tcp_keepalives));
  485. if (err != NULL)
  486. bump("ssh_init: %s", err);
  487. logctx = log_init(NULL, conf);
  488. back->provide_logctx(backhandle, logctx);
  489. console_provide_logctx(logctx);
  490. ssh_scp_init();
  491. if (verbose && realhost != NULL && errs == 0)
  492. tell_user(stderr, "Connected to %s", realhost);
  493. sfree(realhost);
  494. }
  495. /*
  496. * Update statistic information about current file.
  497. */
  498. static void print_stats(char *name, uint64 size, uint64 done,
  499. time_t start, time_t now)
  500. {
  501. float ratebs;
  502. unsigned long eta;
  503. char *etastr;
  504. int pct;
  505. int len;
  506. int elap;
  507. double donedbl;
  508. double sizedbl;
  509. elap = (unsigned long) difftime(now, start);
  510. if (now > start)
  511. ratebs = (float) (uint64_to_double(done) / elap);
  512. else
  513. ratebs = (float) uint64_to_double(done);
  514. if (ratebs < 1.0)
  515. eta = (unsigned long) (uint64_to_double(uint64_subtract(size, done)));
  516. else {
  517. eta = (unsigned long)
  518. ((uint64_to_double(uint64_subtract(size, done)) / ratebs));
  519. }
  520. etastr = dupprintf("%02ld:%02ld:%02ld",
  521. eta / 3600, (eta % 3600) / 60, eta % 60);
  522. donedbl = uint64_to_double(done);
  523. sizedbl = uint64_to_double(size);
  524. pct = (int) (100 * (donedbl * 1.0 / sizedbl));
  525. {
  526. char donekb[40];
  527. /* divide by 1024 to provide kB */
  528. uint64_decimal(uint64_shift_right(done, 10), donekb);
  529. len = printf("\r%-25.25s | %s kB | %5.1f kB/s | ETA: %8s | %3d%%",
  530. name,
  531. donekb, ratebs / 1024.0, etastr, pct);
  532. if (len < prev_stats_len)
  533. printf("%*s", prev_stats_len - len, "");
  534. prev_stats_len = len;
  535. if (uint64_compare(done, size) == 0)
  536. printf("\n");
  537. fflush(stdout);
  538. }
  539. free(etastr);
  540. }
  541. /*
  542. * Find a colon in str and return a pointer to the colon.
  543. * This is used to separate hostname from filename.
  544. */
  545. static char *colon(char *str)
  546. {
  547. /* We ignore a leading colon, since the hostname cannot be
  548. empty. We also ignore a colon as second character because
  549. of filenames like f:myfile.txt. */
  550. if (str[0] == '\0' || str[0] == ':' ||
  551. (str[0] != '[' && str[1] == ':'))
  552. return (NULL);
  553. while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\') {
  554. if (*str == '[') {
  555. /* Skip over IPv6 literal addresses
  556. * (eg: 'jeroen@[2001:db8::1]:myfile.txt') */
  557. char *ipv6_end = strchr(str, ']');
  558. if (ipv6_end) {
  559. str = ipv6_end;
  560. }
  561. }
  562. str++;
  563. }
  564. if (*str == ':')
  565. return (str);
  566. else
  567. return (NULL);
  568. }
  569. /*
  570. * Return a pointer to the portion of str that comes after the last
  571. * slash (or backslash or colon, if `local' is TRUE).
  572. */
  573. static char *stripslashes(char *str, int local)
  574. {
  575. char *p;
  576. if (local) {
  577. p = strchr(str, ':');
  578. if (p) str = p+1;
  579. }
  580. p = strrchr(str, '/');
  581. if (p) str = p+1;
  582. if (local) {
  583. p = strrchr(str, '\\');
  584. if (p) str = p+1;
  585. }
  586. return str;
  587. }
  588. /*
  589. * Determine whether a string is entirely composed of dots.
  590. */
  591. static int is_dots(char *str)
  592. {
  593. return str[strspn(str, ".")] == '\0';
  594. }
  595. /*
  596. * Wait for a response from the other side.
  597. * Return 0 if ok, -1 if error.
  598. */
  599. static int response(void)
  600. {
  601. char ch, resp, rbuf[2048];
  602. int p;
  603. if (ssh_scp_recv((unsigned char *) &resp, 1) <= 0)
  604. bump("Lost connection");
  605. p = 0;
  606. switch (resp) {
  607. case 0: /* ok */
  608. return (0);
  609. default:
  610. rbuf[p++] = resp;
  611. /* fallthrough */
  612. case 1: /* error */
  613. case 2: /* fatal error */
  614. do {
  615. if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)
  616. bump("Protocol error: Lost connection");
  617. rbuf[p++] = ch;
  618. } while (p < sizeof(rbuf) && ch != '\n');
  619. rbuf[p - 1] = '\0';
  620. if (resp == 1)
  621. tell_user(stderr, "%s", rbuf);
  622. else
  623. bump("%s", rbuf);
  624. errs++;
  625. return (-1);
  626. }
  627. }
  628. int sftp_recvdata(char *buf, int len)
  629. {
  630. return ssh_scp_recv((unsigned char *) buf, len);
  631. }
  632. int sftp_senddata(char *buf, int len)
  633. {
  634. back->send(backhandle, buf, len);
  635. return 1;
  636. }
  637. /* ----------------------------------------------------------------------
  638. * sftp-based replacement for the hacky `pscp -ls'.
  639. */
  640. static int sftp_ls_compare(const void *av, const void *bv)
  641. {
  642. const struct fxp_name *a = (const struct fxp_name *) av;
  643. const struct fxp_name *b = (const struct fxp_name *) bv;
  644. return strcmp(a->filename, b->filename);
  645. }
  646. void scp_sftp_listdir(char *dirname)
  647. {
  648. struct fxp_handle *dirh;
  649. struct fxp_names *names;
  650. struct fxp_name *ournames;
  651. struct sftp_packet *pktin;
  652. struct sftp_request *req;
  653. int nnames, namesize;
  654. int i;
  655. if (!fxp_init()) {
  656. tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
  657. errs++;
  658. return;
  659. }
  660. printf("Listing directory %s\n", dirname);
  661. req = fxp_opendir_send(dirname);
  662. pktin = sftp_wait_for_reply(req);
  663. dirh = fxp_opendir_recv(pktin, req);
  664. if (dirh == NULL) {
  665. printf("Unable to open %s: %s\n", dirname, fxp_error());
  666. } else {
  667. nnames = namesize = 0;
  668. ournames = NULL;
  669. while (1) {
  670. req = fxp_readdir_send(dirh);
  671. pktin = sftp_wait_for_reply(req);
  672. names = fxp_readdir_recv(pktin, req);
  673. if (names == NULL) {
  674. if (fxp_error_type() == SSH_FX_EOF)
  675. break;
  676. printf("Reading directory %s: %s\n", dirname, fxp_error());
  677. break;
  678. }
  679. if (names->nnames == 0) {
  680. fxp_free_names(names);
  681. break;
  682. }
  683. if (nnames + names->nnames >= namesize) {
  684. namesize += names->nnames + 128;
  685. ournames = sresize(ournames, namesize, struct fxp_name);
  686. }
  687. for (i = 0; i < names->nnames; i++)
  688. ournames[nnames++] = names->names[i];
  689. names->nnames = 0; /* prevent free_names */
  690. fxp_free_names(names);
  691. }
  692. req = fxp_close_send(dirh);
  693. pktin = sftp_wait_for_reply(req);
  694. fxp_close_recv(pktin, req);
  695. /*
  696. * Now we have our filenames. Sort them by actual file
  697. * name, and then output the longname parts.
  698. */
  699. if (nnames > 0)
  700. qsort(ournames, nnames, sizeof(*ournames), sftp_ls_compare);
  701. /*
  702. * And print them.
  703. */
  704. for (i = 0; i < nnames; i++)
  705. printf("%s\n", ournames[i].longname);
  706. sfree(ournames);
  707. }
  708. }
  709. /* ----------------------------------------------------------------------
  710. * Helper routines that contain the actual SCP protocol elements,
  711. * implemented both as SCP1 and SFTP.
  712. */
  713. static struct scp_sftp_dirstack {
  714. struct scp_sftp_dirstack *next;
  715. struct fxp_name *names;
  716. int namepos, namelen;
  717. char *dirpath;
  718. char *wildcard;
  719. int matched_something; /* wildcard match set was non-empty */
  720. } *scp_sftp_dirstack_head;
  721. static char *scp_sftp_remotepath, *scp_sftp_currentname;
  722. static char *scp_sftp_wildcard;
  723. static int scp_sftp_targetisdir, scp_sftp_donethistarget;
  724. static int scp_sftp_preserve, scp_sftp_recursive;
  725. static unsigned long scp_sftp_mtime, scp_sftp_atime;
  726. static int scp_has_times;
  727. static struct fxp_handle *scp_sftp_filehandle;
  728. static struct fxp_xfer *scp_sftp_xfer;
  729. static uint64 scp_sftp_fileoffset;
  730. int scp_source_setup(char *target, int shouldbedir)
  731. {
  732. if (using_sftp) {
  733. /*
  734. * Find out whether the target filespec is in fact a
  735. * directory.
  736. */
  737. struct sftp_packet *pktin;
  738. struct sftp_request *req;
  739. struct fxp_attrs attrs;
  740. int ret;
  741. if (!fxp_init()) {
  742. tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
  743. errs++;
  744. return 1;
  745. }
  746. req = fxp_stat_send(target);
  747. pktin = sftp_wait_for_reply(req);
  748. ret = fxp_stat_recv(pktin, req, &attrs);
  749. if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))
  750. scp_sftp_targetisdir = 0;
  751. else
  752. scp_sftp_targetisdir = (attrs.permissions & 0040000) != 0;
  753. if (shouldbedir && !scp_sftp_targetisdir) {
  754. bump("pscp: remote filespec %s: not a directory\n", target);
  755. }
  756. scp_sftp_remotepath = dupstr(target);
  757. scp_has_times = 0;
  758. } else {
  759. (void) response();
  760. }
  761. return 0;
  762. }
  763. int scp_send_errmsg(char *str)
  764. {
  765. if (using_sftp) {
  766. /* do nothing; we never need to send our errors to the server */
  767. } else {
  768. back->send(backhandle, "\001", 1);/* scp protocol error prefix */
  769. back->send(backhandle, str, strlen(str));
  770. }
  771. return 0; /* can't fail */
  772. }
  773. int scp_send_filetimes(unsigned long mtime, unsigned long atime)
  774. {
  775. if (using_sftp) {
  776. scp_sftp_mtime = mtime;
  777. scp_sftp_atime = atime;
  778. scp_has_times = 1;
  779. return 0;
  780. } else {
  781. char buf[80];
  782. sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);
  783. back->send(backhandle, buf, strlen(buf));
  784. return response();
  785. }
  786. }
  787. int scp_send_filename(char *name, uint64 size, int permissions)
  788. {
  789. if (using_sftp) {
  790. char *fullname;
  791. struct sftp_packet *pktin;
  792. struct sftp_request *req;
  793. struct fxp_attrs attrs;
  794. if (scp_sftp_targetisdir) {
  795. fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);
  796. } else {
  797. fullname = dupstr(scp_sftp_remotepath);
  798. }
  799. attrs.flags = 0;
  800. PUT_PERMISSIONS(attrs, permissions);
  801. req = fxp_open_send(fullname,
  802. SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC,
  803. &attrs);
  804. pktin = sftp_wait_for_reply(req);
  805. scp_sftp_filehandle = fxp_open_recv(pktin, req);
  806. if (!scp_sftp_filehandle) {
  807. tell_user(stderr, "pscp: unable to open %s: %s",
  808. fullname, fxp_error());
  809. sfree(fullname);
  810. errs++;
  811. return 1;
  812. }
  813. scp_sftp_fileoffset = uint64_make(0, 0);
  814. scp_sftp_xfer = xfer_upload_init(scp_sftp_filehandle,
  815. scp_sftp_fileoffset);
  816. sfree(fullname);
  817. return 0;
  818. } else {
  819. char buf[40];
  820. char sizestr[40];
  821. uint64_decimal(size, sizestr);
  822. if (permissions < 0)
  823. permissions = 0644;
  824. sprintf(buf, "C%04o %s ", (int)(permissions & 07777), sizestr);
  825. back->send(backhandle, buf, strlen(buf));
  826. back->send(backhandle, name, strlen(name));
  827. back->send(backhandle, "\n", 1);
  828. return response();
  829. }
  830. }
  831. int scp_send_filedata(char *data, int len)
  832. {
  833. if (using_sftp) {
  834. int ret;
  835. struct sftp_packet *pktin;
  836. if (!scp_sftp_filehandle) {
  837. return 1;
  838. }
  839. while (!xfer_upload_ready(scp_sftp_xfer)) {
  840. pktin = sftp_recv();
  841. ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
  842. if (ret <= 0) {
  843. tell_user(stderr, "error while writing: %s", fxp_error());
  844. if (ret == INT_MIN) /* pktin not even freed */
  845. sfree(pktin);
  846. errs++;
  847. return 1;
  848. }
  849. }
  850. xfer_upload_data(scp_sftp_xfer, data, len);
  851. scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);
  852. return 0;
  853. } else {
  854. int bufsize = back->send(backhandle, data, len);
  855. /*
  856. * If the network transfer is backing up - that is, the
  857. * remote site is not accepting data as fast as we can
  858. * produce it - then we must loop on network events until
  859. * we have space in the buffer again.
  860. */
  861. while (bufsize > MAX_SCP_BUFSIZE) {
  862. if (ssh_sftp_loop_iteration() < 0)
  863. return 1;
  864. bufsize = back->sendbuffer(backhandle);
  865. }
  866. return 0;
  867. }
  868. }
  869. int scp_send_finish(void)
  870. {
  871. if (using_sftp) {
  872. struct fxp_attrs attrs;
  873. struct sftp_packet *pktin;
  874. struct sftp_request *req;
  875. int ret;
  876. while (!xfer_done(scp_sftp_xfer)) {
  877. pktin = sftp_recv();
  878. ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);
  879. if (ret <= 0) {
  880. tell_user(stderr, "error while writing: %s", fxp_error());
  881. if (ret == INT_MIN) /* pktin not even freed */
  882. sfree(pktin);
  883. errs++;
  884. return 1;
  885. }
  886. }
  887. xfer_cleanup(scp_sftp_xfer);
  888. if (!scp_sftp_filehandle) {
  889. return 1;
  890. }
  891. if (scp_has_times) {
  892. attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;
  893. attrs.atime = scp_sftp_atime;
  894. attrs.mtime = scp_sftp_mtime;
  895. req = fxp_fsetstat_send(scp_sftp_filehandle, attrs);
  896. pktin = sftp_wait_for_reply(req);
  897. ret = fxp_fsetstat_recv(pktin, req);
  898. if (!ret) {
  899. tell_user(stderr, "unable to set file times: %s", fxp_error());
  900. errs++;
  901. }
  902. }
  903. req = fxp_close_send(scp_sftp_filehandle);
  904. pktin = sftp_wait_for_reply(req);
  905. fxp_close_recv(pktin, req);
  906. scp_has_times = 0;
  907. return 0;
  908. } else {
  909. back->send(backhandle, "", 1);
  910. return response();
  911. }
  912. }
  913. char *scp_save_remotepath(void)
  914. {
  915. if (using_sftp)
  916. return scp_sftp_remotepath;
  917. else
  918. return NULL;
  919. }
  920. void scp_restore_remotepath(char *data)
  921. {
  922. if (using_sftp)
  923. scp_sftp_remotepath = data;
  924. }
  925. int scp_send_dirname(char *name, int modes)
  926. {
  927. if (using_sftp) {
  928. char *fullname;
  929. char const *err;
  930. struct fxp_attrs attrs;
  931. struct sftp_packet *pktin;
  932. struct sftp_request *req;
  933. int ret;
  934. if (scp_sftp_targetisdir) {
  935. fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);
  936. } else {
  937. fullname = dupstr(scp_sftp_remotepath);
  938. }
  939. /*
  940. * We don't worry about whether we managed to create the
  941. * directory, because if it exists already it's OK just to
  942. * use it. Instead, we will stat it afterwards, and if it
  943. * exists and is a directory we will assume we were either
  944. * successful or it didn't matter.
  945. */
  946. req = fxp_mkdir_send(fullname);
  947. pktin = sftp_wait_for_reply(req);
  948. ret = fxp_mkdir_recv(pktin, req);
  949. if (!ret)
  950. err = fxp_error();
  951. else
  952. err = "server reported no error";
  953. req = fxp_stat_send(fullname);
  954. pktin = sftp_wait_for_reply(req);
  955. ret = fxp_stat_recv(pktin, req, &attrs);
  956. if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||
  957. !(attrs.permissions & 0040000)) {
  958. tell_user(stderr, "unable to create directory %s: %s",
  959. fullname, err);
  960. sfree(fullname);
  961. errs++;
  962. return 1;
  963. }
  964. scp_sftp_remotepath = fullname;
  965. return 0;
  966. } else {
  967. char buf[40];
  968. sprintf(buf, "D%04o 0 ", modes);
  969. back->send(backhandle, buf, strlen(buf));
  970. back->send(backhandle, name, strlen(name));
  971. back->send(backhandle, "\n", 1);
  972. return response();
  973. }
  974. }
  975. int scp_send_enddir(void)
  976. {
  977. if (using_sftp) {
  978. sfree(scp_sftp_remotepath);
  979. return 0;
  980. } else {
  981. back->send(backhandle, "E\n", 2);
  982. return response();
  983. }
  984. }
  985. /*
  986. * Yes, I know; I have an scp_sink_setup _and_ an scp_sink_init.
  987. * That's bad. The difference is that scp_sink_setup is called once
  988. * right at the start, whereas scp_sink_init is called to
  989. * initialise every level of recursion in the protocol.
  990. */
  991. int scp_sink_setup(char *source, int preserve, int recursive)
  992. {
  993. if (using_sftp) {
  994. char *newsource;
  995. if (!fxp_init()) {
  996. tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());
  997. errs++;
  998. return 1;
  999. }
  1000. /*
  1001. * It's possible that the source string we've been given
  1002. * contains a wildcard. If so, we must split the directory
  1003. * away from the wildcard itself (throwing an error if any
  1004. * wildcardness comes before the final slash) and arrange
  1005. * things so that a dirstack entry will be set up.
  1006. */
  1007. newsource = snewn(1+strlen(source), char);
  1008. if (!wc_unescape(newsource, source)) {
  1009. /* Yes, here we go; it's a wildcard. Bah. */
  1010. char *dupsource, *lastpart, *dirpart, *wildcard;
  1011. sfree(newsource);
  1012. dupsource = dupstr(source);
  1013. lastpart = stripslashes(dupsource, 0);
  1014. wildcard = dupstr(lastpart);
  1015. *lastpart = '\0';
  1016. if (*dupsource && dupsource[1]) {
  1017. /*
  1018. * The remains of dupsource are at least two
  1019. * characters long, meaning the pathname wasn't
  1020. * empty or just `/'. Hence, we remove the trailing
  1021. * slash.
  1022. */
  1023. lastpart[-1] = '\0';
  1024. } else if (!*dupsource) {
  1025. /*
  1026. * The remains of dupsource are _empty_ - the whole
  1027. * pathname was a wildcard. Hence we need to
  1028. * replace it with ".".
  1029. */
  1030. sfree(dupsource);
  1031. dupsource = dupstr(".");
  1032. }
  1033. /*
  1034. * Now we have separated our string into dupsource (the
  1035. * directory part) and wildcard. Both of these will
  1036. * need freeing at some point. Next step is to remove
  1037. * wildcard escapes from the directory part, throwing
  1038. * an error if it contains a real wildcard.
  1039. */
  1040. dirpart = snewn(1+strlen(dupsource), char);
  1041. if (!wc_unescape(dirpart, dupsource)) {
  1042. tell_user(stderr, "%s: multiple-level wildcards unsupported",
  1043. source);
  1044. errs++;
  1045. sfree(dirpart);
  1046. sfree(wildcard);
  1047. sfree(dupsource);
  1048. return 1;
  1049. }
  1050. /*
  1051. * Now we have dirpart (unescaped, ie a valid remote
  1052. * path), and wildcard (a wildcard). This will be
  1053. * sufficient to arrange a dirstack entry.
  1054. */
  1055. scp_sftp_remotepath = dirpart;
  1056. scp_sftp_wildcard = wildcard;
  1057. sfree(dupsource);
  1058. } else {
  1059. scp_sftp_remotepath = newsource;
  1060. scp_sftp_wildcard = NULL;
  1061. }
  1062. scp_sftp_preserve = preserve;
  1063. scp_sftp_recursive = recursive;
  1064. scp_sftp_donethistarget = 0;
  1065. scp_sftp_dirstack_head = NULL;
  1066. }
  1067. return 0;
  1068. }
  1069. int scp_sink_init(void)
  1070. {
  1071. if (!using_sftp) {
  1072. back->send(backhandle, "", 1);
  1073. }
  1074. return 0;
  1075. }
  1076. #define SCP_SINK_FILE 1
  1077. #define SCP_SINK_DIR 2
  1078. #define SCP_SINK_ENDDIR 3
  1079. #define SCP_SINK_RETRY 4 /* not an action; just try again */
  1080. struct scp_sink_action {
  1081. int action; /* FILE, DIR, ENDDIR */
  1082. char *buf; /* will need freeing after use */
  1083. char *name; /* filename or dirname (not ENDDIR) */
  1084. long permissions; /* access permissions (not ENDDIR) */
  1085. uint64 size; /* file size (not ENDDIR) */
  1086. int settime; /* 1 if atime and mtime are filled */
  1087. unsigned long atime, mtime; /* access times for the file */
  1088. };
  1089. int scp_get_sink_action(struct scp_sink_action *act)
  1090. {
  1091. if (using_sftp) {
  1092. char *fname;
  1093. int must_free_fname;
  1094. struct fxp_attrs attrs;
  1095. struct sftp_packet *pktin;
  1096. struct sftp_request *req;
  1097. int ret;
  1098. if (!scp_sftp_dirstack_head) {
  1099. if (!scp_sftp_donethistarget) {
  1100. /*
  1101. * Simple case: we are only dealing with one file.
  1102. */
  1103. fname = scp_sftp_remotepath;
  1104. must_free_fname = 0;
  1105. scp_sftp_donethistarget = 1;
  1106. } else {
  1107. /*
  1108. * Even simpler case: one file _which we've done_.
  1109. * Return 1 (finished).
  1110. */
  1111. return 1;
  1112. }
  1113. } else {
  1114. /*
  1115. * We're now in the middle of stepping through a list
  1116. * of names returned from fxp_readdir(); so let's carry
  1117. * on.
  1118. */
  1119. struct scp_sftp_dirstack *head = scp_sftp_dirstack_head;
  1120. while (head->namepos < head->namelen &&
  1121. (is_dots(head->names[head->namepos].filename) ||
  1122. (head->wildcard &&
  1123. !wc_match(head->wildcard,
  1124. head->names[head->namepos].filename))))
  1125. head->namepos++; /* skip . and .. */
  1126. if (head->namepos < head->namelen) {
  1127. head->matched_something = 1;
  1128. fname = dupcat(head->dirpath, "/",
  1129. head->names[head->namepos++].filename,
  1130. NULL);
  1131. must_free_fname = 1;
  1132. } else {
  1133. /*
  1134. * We've come to the end of the list; pop it off
  1135. * the stack and return an ENDDIR action (or RETRY
  1136. * if this was a wildcard match).
  1137. */
  1138. if (head->wildcard) {
  1139. act->action = SCP_SINK_RETRY;
  1140. if (!head->matched_something) {
  1141. tell_user(stderr, "pscp: wildcard '%s' matched "
  1142. "no files", head->wildcard);
  1143. errs++;
  1144. }
  1145. sfree(head->wildcard);
  1146. } else {
  1147. act->action = SCP_SINK_ENDDIR;
  1148. }
  1149. sfree(head->dirpath);
  1150. sfree(head->names);
  1151. scp_sftp_dirstack_head = head->next;
  1152. sfree(head);
  1153. return 0;
  1154. }
  1155. }
  1156. /*
  1157. * Now we have a filename. Stat it, and see if it's a file
  1158. * or a directory.
  1159. */
  1160. req = fxp_stat_send(fname);
  1161. pktin = sftp_wait_for_reply(req);
  1162. ret = fxp_stat_recv(pktin, req, &attrs);
  1163. if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
  1164. tell_user(stderr, "unable to identify %s: %s", fname,
  1165. ret ? "file type not supplied" : fxp_error());
  1166. if (must_free_fname) sfree(fname);
  1167. errs++;
  1168. return 1;
  1169. }
  1170. if (attrs.permissions & 0040000) {
  1171. struct scp_sftp_dirstack *newitem;
  1172. struct fxp_handle *dirhandle;
  1173. int nnames, namesize;
  1174. struct fxp_name *ournames;
  1175. struct fxp_names *names;
  1176. /*
  1177. * It's a directory. If we're not in recursive mode,
  1178. * this merits a complaint (which is fatal if the name
  1179. * was specified directly, but not if it was matched by
  1180. * a wildcard).
  1181. *
  1182. * We skip this complaint completely if
  1183. * scp_sftp_wildcard is set, because that's an
  1184. * indication that we're not actually supposed to
  1185. * _recursively_ transfer the dir, just scan it for
  1186. * things matching the wildcard.
  1187. */
  1188. if (!scp_sftp_recursive && !scp_sftp_wildcard) {
  1189. tell_user(stderr, "pscp: %s: is a directory", fname);
  1190. errs++;
  1191. if (must_free_fname) sfree(fname);
  1192. if (scp_sftp_dirstack_head) {
  1193. act->action = SCP_SINK_RETRY;
  1194. return 0;
  1195. } else {
  1196. return 1;
  1197. }
  1198. }
  1199. /*
  1200. * Otherwise, the fun begins. We must fxp_opendir() the
  1201. * directory, slurp the filenames into memory, return
  1202. * SCP_SINK_DIR (unless this is a wildcard match), and
  1203. * set targetisdir. The next time we're called, we will
  1204. * run through the list of filenames one by one,
  1205. * matching them against a wildcard if present.
  1206. *
  1207. * If targetisdir is _already_ set (meaning we're
  1208. * already in the middle of going through another such
  1209. * list), we must push the other (target,namelist) pair
  1210. * on a stack.
  1211. */
  1212. req = fxp_opendir_send(fname);
  1213. pktin = sftp_wait_for_reply(req);
  1214. dirhandle = fxp_opendir_recv(pktin, req);
  1215. if (!dirhandle) {
  1216. tell_user(stderr, "pscp: unable to open directory %s: %s",
  1217. fname, fxp_error());
  1218. if (must_free_fname) sfree(fname);
  1219. errs++;
  1220. return 1;
  1221. }
  1222. nnames = namesize = 0;
  1223. ournames = NULL;
  1224. while (1) {
  1225. int i;
  1226. req = fxp_readdir_send(dirhandle);
  1227. pktin = sftp_wait_for_reply(req);
  1228. names = fxp_readdir_recv(pktin, req);
  1229. if (names == NULL) {
  1230. if (fxp_error_type() == SSH_FX_EOF)
  1231. break;
  1232. tell_user(stderr, "pscp: reading directory %s: %s",
  1233. fname, fxp_error());
  1234. req = fxp_close_send(dirhandle);
  1235. pktin = sftp_wait_for_reply(req);
  1236. fxp_close_recv(pktin, req);
  1237. if (must_free_fname) sfree(fname);
  1238. sfree(ournames);
  1239. errs++;
  1240. return 1;
  1241. }
  1242. if (names->nnames == 0) {
  1243. fxp_free_names(names);
  1244. break;
  1245. }
  1246. if (nnames + names->nnames >= namesize) {
  1247. namesize += names->nnames + 128;
  1248. ournames = sresize(ournames, namesize, struct fxp_name);
  1249. }
  1250. for (i = 0; i < names->nnames; i++) {
  1251. if (!strcmp(names->names[i].filename, ".") ||
  1252. !strcmp(names->names[i].filename, "..")) {
  1253. /*
  1254. * . and .. are normal consequences of
  1255. * reading a directory, and aren't worth
  1256. * complaining about.
  1257. */
  1258. } else if (!vet_filename(names->names[i].filename)) {
  1259. tell_user(stderr, "ignoring potentially dangerous server-"
  1260. "supplied filename '%s'",
  1261. names->names[i].filename);
  1262. } else
  1263. ournames[nnames++] = names->names[i];
  1264. }
  1265. names->nnames = 0; /* prevent free_names */
  1266. fxp_free_names(names);
  1267. }
  1268. req = fxp_close_send(dirhandle);
  1269. pktin = sftp_wait_for_reply(req);
  1270. fxp_close_recv(pktin, req);
  1271. newitem = snew(struct scp_sftp_dirstack);
  1272. newitem->next = scp_sftp_dirstack_head;
  1273. newitem->names = ournames;
  1274. newitem->namepos = 0;
  1275. newitem->namelen = nnames;
  1276. if (must_free_fname)
  1277. newitem->dirpath = fname;
  1278. else
  1279. newitem->dirpath = dupstr(fname);
  1280. if (scp_sftp_wildcard) {
  1281. newitem->wildcard = scp_sftp_wildcard;
  1282. newitem->matched_something = 0;
  1283. scp_sftp_wildcard = NULL;
  1284. } else {
  1285. newitem->wildcard = NULL;
  1286. }
  1287. scp_sftp_dirstack_head = newitem;
  1288. if (newitem->wildcard) {
  1289. act->action = SCP_SINK_RETRY;
  1290. } else {
  1291. act->action = SCP_SINK_DIR;
  1292. act->buf = dupstr(stripslashes(fname, 0));
  1293. act->name = act->buf;
  1294. act->size = uint64_make(0,0); /* duhh, it's a directory */
  1295. act->permissions = 07777 & attrs.permissions;
  1296. if (scp_sftp_preserve &&
  1297. (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
  1298. act->atime = attrs.atime;
  1299. act->mtime = attrs.mtime;
  1300. act->settime = 1;
  1301. } else
  1302. act->settime = 0;
  1303. }
  1304. return 0;
  1305. } else {
  1306. /*
  1307. * It's a file. Return SCP_SINK_FILE.
  1308. */
  1309. act->action = SCP_SINK_FILE;
  1310. act->buf = dupstr(stripslashes(fname, 0));
  1311. act->name = act->buf;
  1312. if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
  1313. act->size = attrs.size;
  1314. } else
  1315. act->size = uint64_make(ULONG_MAX,ULONG_MAX); /* no idea */
  1316. act->permissions = 07777 & attrs.permissions;
  1317. if (scp_sftp_preserve &&
  1318. (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
  1319. act->atime = attrs.atime;
  1320. act->mtime = attrs.mtime;
  1321. act->settime = 1;
  1322. } else
  1323. act->settime = 0;
  1324. if (must_free_fname)
  1325. scp_sftp_currentname = fname;
  1326. else
  1327. scp_sftp_currentname = dupstr(fname);
  1328. return 0;
  1329. }
  1330. } else {
  1331. int done = 0;
  1332. int i, bufsize;
  1333. int action;
  1334. char ch;
  1335. act->settime = 0;
  1336. act->buf = NULL;
  1337. bufsize = 0;
  1338. while (!done) {
  1339. if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)
  1340. return 1;
  1341. if (ch == '\n')
  1342. bump("Protocol error: Unexpected newline");
  1343. i = 0;
  1344. action = ch;
  1345. do {
  1346. if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)
  1347. bump("Lost connection");
  1348. if (i >= bufsize) {
  1349. bufsize = i + 128;
  1350. act->buf = sresize(act->buf, bufsize, char);
  1351. }
  1352. act->buf[i++] = ch;
  1353. } while (ch != '\n');
  1354. act->buf[i - 1] = '\0';
  1355. switch (action) {
  1356. case '\01': /* error */
  1357. tell_user(stderr, "%s", act->buf);
  1358. errs++;
  1359. continue; /* go round again */
  1360. case '\02': /* fatal error */
  1361. bump("%s", act->buf);
  1362. case 'E':
  1363. back->send(backhandle, "", 1);
  1364. act->action = SCP_SINK_ENDDIR;
  1365. return 0;
  1366. case 'T':
  1367. if (sscanf(act->buf, "%ld %*d %ld %*d",
  1368. &act->mtime, &act->atime) == 2) {
  1369. act->settime = 1;
  1370. back->send(backhandle, "", 1);
  1371. continue; /* go round again */
  1372. }
  1373. bump("Protocol error: Illegal time format");
  1374. case 'C':
  1375. case 'D':
  1376. act->action = (action == 'C' ? SCP_SINK_FILE : SCP_SINK_DIR);
  1377. break;
  1378. default:
  1379. bump("Protocol error: Expected control record");
  1380. }
  1381. /*
  1382. * We will go round this loop only once, unless we hit
  1383. * `continue' above.
  1384. */
  1385. done = 1;
  1386. }
  1387. /*
  1388. * If we get here, we must have seen SCP_SINK_FILE or
  1389. * SCP_SINK_DIR.
  1390. */
  1391. {
  1392. char sizestr[40];
  1393. if (sscanf(act->buf, "%lo %s %n", &act->permissions,
  1394. sizestr, &i) != 2)
  1395. bump("Protocol error: Illegal file descriptor format");
  1396. act->size = uint64_from_decimal(sizestr);
  1397. act->name = act->buf + i;
  1398. return 0;
  1399. }
  1400. }
  1401. }
  1402. int scp_accept_filexfer(void)
  1403. {
  1404. if (using_sftp) {
  1405. struct sftp_packet *pktin;
  1406. struct sftp_request *req;
  1407. req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ, NULL);
  1408. pktin = sftp_wait_for_reply(req);
  1409. scp_sftp_filehandle = fxp_open_recv(pktin, req);
  1410. if (!scp_sftp_filehandle) {
  1411. tell_user(stderr, "pscp: unable to open %s: %s",
  1412. scp_sftp_currentname, fxp_error());
  1413. errs++;
  1414. return 1;
  1415. }
  1416. scp_sftp_fileoffset = uint64_make(0, 0);
  1417. scp_sftp_xfer = xfer_download_init(scp_sftp_filehandle,
  1418. scp_sftp_fileoffset);
  1419. sfree(scp_sftp_currentname);
  1420. return 0;
  1421. } else {
  1422. back->send(backhandle, "", 1);
  1423. return 0; /* can't fail */
  1424. }
  1425. }
  1426. int scp_recv_filedata(char *data, int len)
  1427. {
  1428. if (using_sftp) {
  1429. struct sftp_packet *pktin;
  1430. int ret, actuallen;
  1431. void *vbuf;
  1432. xfer_download_queue(scp_sftp_xfer);
  1433. pktin = sftp_recv();
  1434. ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
  1435. if (ret <= 0) {
  1436. tell_user(stderr, "pscp: error while reading: %s", fxp_error());
  1437. if (ret == INT_MIN) /* pktin not even freed */
  1438. sfree(pktin);
  1439. errs++;
  1440. return -1;
  1441. }
  1442. if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {
  1443. /*
  1444. * This assertion relies on the fact that the natural
  1445. * block size used in the xfer manager is at most that
  1446. * used in this module. I don't like crossing layers in
  1447. * this way, but it'll do for now.
  1448. */
  1449. assert(actuallen <= len);
  1450. memcpy(data, vbuf, actuallen);
  1451. sfree(vbuf);
  1452. } else
  1453. actuallen = 0;
  1454. scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, actuallen);
  1455. return actuallen;
  1456. } else {
  1457. return ssh_scp_recv((unsigned char *) data, len);
  1458. }
  1459. }
  1460. int scp_finish_filerecv(void)
  1461. {
  1462. if (using_sftp) {
  1463. struct sftp_packet *pktin;
  1464. struct sftp_request *req;
  1465. /*
  1466. * Ensure that xfer_done() will work correctly, so we can
  1467. * clean up any outstanding requests from the file
  1468. * transfer.
  1469. */
  1470. xfer_set_error(scp_sftp_xfer);
  1471. while (!xfer_done(scp_sftp_xfer)) {
  1472. void *vbuf;
  1473. int ret, len;
  1474. pktin = sftp_recv();
  1475. ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);
  1476. if (ret <= 0) {
  1477. tell_user(stderr, "pscp: error while reading: %s", fxp_error());
  1478. if (ret == INT_MIN) /* pktin not even freed */
  1479. sfree(pktin);
  1480. errs++;
  1481. return -1;
  1482. }
  1483. if (xfer_download_data(scp_sftp_xfer, &vbuf, &len))
  1484. sfree(vbuf);
  1485. }
  1486. xfer_cleanup(scp_sftp_xfer);
  1487. req = fxp_close_send(scp_sftp_filehandle);
  1488. pktin = sftp_wait_for_reply(req);
  1489. fxp_close_recv(pktin, req);
  1490. return 0;
  1491. } else {
  1492. back->send(backhandle, "", 1);
  1493. return response();
  1494. }
  1495. }
  1496. /* ----------------------------------------------------------------------
  1497. * Send an error message to the other side and to the screen.
  1498. * Increment error counter.
  1499. */
  1500. static void run_err(const char *fmt, ...)
  1501. {
  1502. char *str, *str2;
  1503. va_list ap;
  1504. va_start(ap, fmt);
  1505. errs++;
  1506. str = dupvprintf(fmt, ap);
  1507. str2 = dupcat("pscp: ", str, "\n", NULL);
  1508. sfree(str);
  1509. scp_send_errmsg(str2);
  1510. tell_user(stderr, "%s", str2);
  1511. va_end(ap);
  1512. sfree(str2);
  1513. }
  1514. /*
  1515. * Execute the source part of the SCP protocol.
  1516. */
  1517. static void source(char *src)
  1518. {
  1519. uint64 size;
  1520. unsigned long mtime, atime;
  1521. long permissions;
  1522. char *last;
  1523. RFile *f;
  1524. int attr;
  1525. uint64 i;
  1526. uint64 stat_bytes;
  1527. time_t stat_starttime, stat_lasttime;
  1528. attr = file_type(src);
  1529. if (attr == FILE_TYPE_NONEXISTENT ||
  1530. attr == FILE_TYPE_WEIRD) {
  1531. run_err("%s: %s file or directory", src,
  1532. (attr == FILE_TYPE_WEIRD ? "Not a" : "No such"));
  1533. return;
  1534. }
  1535. if (attr == FILE_TYPE_DIRECTORY) {
  1536. if (recursive) {
  1537. /*
  1538. * Avoid . and .. directories.
  1539. */
  1540. char *p;
  1541. p = strrchr(src, '/');
  1542. if (!p)
  1543. p = strrchr(src, '\\');
  1544. if (!p)
  1545. p = src;
  1546. else
  1547. p++;
  1548. if (!strcmp(p, ".") || !strcmp(p, ".."))
  1549. /* skip . and .. */ ;
  1550. else
  1551. rsource(src);
  1552. } else {
  1553. run_err("%s: not a regular file", src);
  1554. }
  1555. return;
  1556. }
  1557. if ((last = strrchr(src, '/')) == NULL)
  1558. last = src;
  1559. else
  1560. last++;
  1561. if (strrchr(last, '\\') != NULL)
  1562. last = strrchr(last, '\\') + 1;
  1563. if (last == src && strchr(src, ':') != NULL)
  1564. last = strchr(src, ':') + 1;
  1565. f = open_existing_file(src, &size, &mtime, &atime, &permissions);
  1566. if (f == NULL) {
  1567. run_err("%s: Cannot open file", src);
  1568. return;
  1569. }
  1570. if (preserve) {
  1571. if (scp_send_filetimes(mtime, atime)) {
  1572. close_rfile(f);
  1573. return;
  1574. }
  1575. }
  1576. if (verbose) {
  1577. char sizestr[40];
  1578. uint64_decimal(size, sizestr);
  1579. tell_user(stderr, "Sending file %s, size=%s", last, sizestr);
  1580. }
  1581. if (scp_send_filename(last, size, permissions)) {
  1582. close_rfile(f);
  1583. return;
  1584. }
  1585. stat_bytes = uint64_make(0,0);
  1586. stat_starttime = time(NULL);
  1587. stat_lasttime = 0;
  1588. for (i = uint64_make(0,0);
  1589. uint64_compare(i,size) < 0;
  1590. i = uint64_add32(i,4096)) {
  1591. char transbuf[4096];
  1592. int j, k = 4096;
  1593. if (uint64_compare(uint64_add32(i, k),size) > 0) /* i + k > size */
  1594. k = (uint64_subtract(size, i)).lo; /* k = size - i; */
  1595. if ((j = read_from_file(f, transbuf, k)) != k) {
  1596. if (statistics)
  1597. printf("\n");
  1598. bump("%s: Read error", src);
  1599. }
  1600. if (scp_send_filedata(transbuf, k))
  1601. bump("%s: Network error occurred", src);
  1602. if (statistics) {
  1603. stat_bytes = uint64_add32(stat_bytes, k);
  1604. if (time(NULL) != stat_lasttime ||
  1605. (uint64_compare(uint64_add32(i, k), size) == 0)) {
  1606. stat_lasttime = time(NULL);
  1607. print_stats(last, size, stat_bytes,
  1608. stat_starttime, stat_lasttime);
  1609. }
  1610. }
  1611. }
  1612. close_rfile(f);
  1613. (void) scp_send_finish();
  1614. }
  1615. /*
  1616. * Recursively send the contents of a directory.
  1617. */
  1618. static void rsource(char *src)
  1619. {
  1620. char *last;
  1621. char *save_target;
  1622. DirHandle *dir;
  1623. if ((last = strrchr(src, '/')) == NULL)
  1624. last = src;
  1625. else
  1626. last++;
  1627. if (strrchr(last, '\\') != NULL)
  1628. last = strrchr(last, '\\') + 1;
  1629. if (last == src && strchr(src, ':') != NULL)
  1630. last = strchr(src, ':') + 1;
  1631. /* maybe send filetime */
  1632. save_target = scp_save_remotepath();
  1633. if (verbose)
  1634. tell_user(stderr, "Entering directory: %s", last);
  1635. if (scp_send_dirname(last, 0755))
  1636. return;
  1637. dir = open_directory(src);
  1638. if (dir != NULL) {
  1639. char *filename;
  1640. while ((filename = read_filename(dir)) != NULL) {
  1641. char *foundfile = dupcat(src, "/", filename, NULL);
  1642. source(foundfile);
  1643. sfree(foundfile);
  1644. sfree(filename);
  1645. }
  1646. }
  1647. close_directory(dir);
  1648. (void) scp_send_enddir();
  1649. scp_restore_remotepath(save_target);
  1650. }
  1651. /*
  1652. * Execute the sink part of the SCP protocol.
  1653. */
  1654. static void sink(char *targ, char *src)
  1655. {
  1656. char *destfname;
  1657. int targisdir = 0;
  1658. int exists;
  1659. int attr;
  1660. WFile *f;
  1661. uint64 received;
  1662. int wrerror = 0;
  1663. uint64 stat_bytes;
  1664. time_t stat_starttime, stat_lasttime;
  1665. char *stat_name;
  1666. attr = file_type(targ);
  1667. if (attr == FILE_TYPE_DIRECTORY)
  1668. targisdir = 1;
  1669. if (targetshouldbedirectory && !targisdir)
  1670. bump("%s: Not a directory", targ);
  1671. scp_sink_init();
  1672. while (1) {
  1673. struct scp_sink_action act;
  1674. if (scp_get_sink_action(&act))
  1675. return;
  1676. if (act.action == SCP_SINK_ENDDIR)
  1677. return;
  1678. if (act.action == SCP_SINK_RETRY)
  1679. continue;
  1680. if (targisdir) {
  1681. /*
  1682. * Prevent the remote side from maliciously writing to
  1683. * files outside the target area by sending a filename
  1684. * containing `../'. In fact, it shouldn't be sending
  1685. * filenames with any slashes or colons in at all; so
  1686. * we'll find the last slash, backslash or colon in the
  1687. * filename and use only the part after that. (And
  1688. * warn!)
  1689. *
  1690. * In addition, we also ensure here that if we're
  1691. * copying a single file and the target is a directory
  1692. * (common usage: `pscp host:filename .') the remote
  1693. * can't send us a _different_ file name. We can
  1694. * distinguish this case because `src' will be non-NULL
  1695. * and the last component of that will fail to match
  1696. * (the last component of) the name sent.
  1697. *
  1698. * Well, not always; if `src' is a wildcard, we do
  1699. * expect to get back filenames that don't correspond
  1700. * exactly to it. Ideally in this case, we would like
  1701. * to ensure that the returned filename actually
  1702. * matches the wildcard pattern - but one of SCP's
  1703. * protocol infelicities is that wildcard matching is
  1704. * done at the server end _by the server's rules_ and
  1705. * so in general this is infeasible. Hence, we only
  1706. * accept filenames that don't correspond to `src' if
  1707. * unsafe mode is enabled or we are using SFTP (which
  1708. * resolves remote wildcards on the client side and can
  1709. * be trusted).
  1710. */
  1711. char *striptarget, *stripsrc;
  1712. striptarget = stripslashes(act.name, 1);
  1713. if (striptarget != act.name) {
  1714. tell_user(stderr, "warning: remote host sent a compound"
  1715. " pathname '%s'", act.name);
  1716. tell_user(stderr, " renaming local file to '%s'",
  1717. striptarget);
  1718. }
  1719. /*
  1720. * Also check to see if the target filename is '.' or
  1721. * '..', or indeed '...' and so on because Windows
  1722. * appears to interpret those like '..'.
  1723. */
  1724. if (is_dots(striptarget)) {
  1725. bump("security violation: remote host attempted to write to"
  1726. " a '.' or '..' path!");
  1727. }
  1728. if (src) {
  1729. stripsrc = stripslashes(src, 1);
  1730. if (strcmp(striptarget, stripsrc) &&
  1731. !using_sftp && !scp_unsafe_mode) {
  1732. tell_user(stderr, "warning: remote host tried to write "
  1733. "to a file called '%s'", striptarget);
  1734. tell_user(stderr, " when we requested a file "
  1735. "called '%s'.", stripsrc);
  1736. tell_user(stderr, " If this is a wildcard, "
  1737. "consider upgrading to SSH-2 or using");
  1738. tell_user(stderr, " the '-unsafe' option. Renaming"
  1739. " of this file has been disallowed.");
  1740. /* Override the name the server provided with our own. */
  1741. striptarget = stripsrc;
  1742. }
  1743. }
  1744. if (targ[0] != '\0')
  1745. destfname = dir_file_cat(targ, striptarget);
  1746. else
  1747. destfname = dupstr(striptarget);
  1748. } else {
  1749. /*
  1750. * In this branch of the if, the target area is a
  1751. * single file with an explicitly specified name in any
  1752. * case, so there's no danger.
  1753. */
  1754. destfname = dupstr(targ);
  1755. }
  1756. attr = file_type(destfname);
  1757. exists = (attr != FILE_TYPE_NONEXISTENT);
  1758. if (act.action == SCP_SINK_DIR) {
  1759. if (exists && attr != FILE_TYPE_DIRECTORY) {
  1760. run_err("%s: Not a directory", destfname);
  1761. sfree(destfname);
  1762. continue;
  1763. }
  1764. if (!exists) {
  1765. if (!create_directory(destfname)) {
  1766. run_err("%s: Cannot create directory", destfname);
  1767. sfree(destfname);
  1768. continue;
  1769. }
  1770. }
  1771. sink(destfname, NULL);
  1772. /* can we set the timestamp for directories ? */
  1773. sfree(destfname);
  1774. continue;
  1775. }
  1776. f = open_new_file(destfname, act.permissions);
  1777. if (f == NULL) {
  1778. run_err("%s: Cannot create file", destfname);
  1779. sfree(destfname);
  1780. continue;
  1781. }
  1782. if (scp_accept_filexfer()) {
  1783. sfree(destfname);
  1784. close_wfile(f);
  1785. return;
  1786. }
  1787. stat_bytes = uint64_make(0, 0);
  1788. stat_starttime = time(NULL);
  1789. stat_lasttime = 0;
  1790. stat_name = stripslashes(destfname, 1);
  1791. received = uint64_make(0, 0);
  1792. while (uint64_compare(received,act.size) < 0) {
  1793. char transbuf[32768];
  1794. uint64 blksize;
  1795. int read;
  1796. blksize = uint64_make(0, 32768);
  1797. if (uint64_compare(blksize,uint64_subtract(act.size,received)) > 0)
  1798. blksize = uint64_subtract(act.size,received);
  1799. read = scp_recv_filedata(transbuf, (int)blksize.lo);
  1800. if (read <= 0)
  1801. bump("Lost connection");
  1802. if (wrerror)
  1803. continue;
  1804. if (write_to_file(f, transbuf, read) != (int)read) {
  1805. wrerror = 1;
  1806. /* FIXME: in sftp we can actually abort the transfer */
  1807. if (statistics)
  1808. printf("\r%-25.25s | %50s\n",
  1809. stat_name,
  1810. "Write error.. waiting for end of file");
  1811. continue;
  1812. }
  1813. if (statistics) {
  1814. stat_bytes = uint64_add32(stat_bytes,read);
  1815. if (time(NULL) > stat_lasttime ||
  1816. uint64_compare(uint64_add32(received, read), act.size) == 0) {
  1817. stat_lasttime = time(NULL);
  1818. print_stats(stat_name, act.size, stat_bytes,
  1819. stat_starttime, stat_lasttime);
  1820. }
  1821. }
  1822. received = uint64_add32(received, read);
  1823. }
  1824. if (act.settime) {
  1825. set_file_times(f, act.mtime, act.atime);
  1826. }
  1827. close_wfile(f);
  1828. if (wrerror) {
  1829. run_err("%s: Write error", destfname);
  1830. sfree(destfname);
  1831. continue;
  1832. }
  1833. (void) scp_finish_filerecv();
  1834. sfree(destfname);
  1835. sfree(act.buf);
  1836. }
  1837. }
  1838. /*
  1839. * We will copy local files to a remote server.
  1840. */
  1841. static void toremote(int argc, char *argv[])
  1842. {
  1843. char *src, *targ, *host, *user;
  1844. char *cmd;
  1845. int i, wc_type;
  1846. targ = argv[argc - 1];
  1847. /* Separate host from filename */
  1848. host = targ;
  1849. targ = colon(targ);
  1850. if (targ == NULL)
  1851. bump("targ == NULL in toremote()");
  1852. *targ++ = '\0';
  1853. if (*targ == '\0')
  1854. targ = ".";
  1855. /* Substitute "." for empty target */
  1856. /* Separate host and username */
  1857. user = host;
  1858. host = strrchr(host, '@');
  1859. if (host == NULL) {
  1860. host = user;
  1861. user = NULL;
  1862. } else {
  1863. *host++ = '\0';
  1864. if (*user == '\0')
  1865. user = NULL;
  1866. }
  1867. if (argc == 2) {
  1868. if (colon(argv[0]) != NULL)
  1869. bump("%s: Remote to remote not supported", argv[0]);
  1870. wc_type = test_wildcard(argv[0], 1);
  1871. if (wc_type == WCTYPE_NONEXISTENT)
  1872. bump("%s: No such file or directory\n", argv[0]);
  1873. else if (wc_type == WCTYPE_WILDCARD)
  1874. targetshouldbedirectory = 1;
  1875. }
  1876. cmd = dupprintf("scp%s%s%s%s -t %s",
  1877. verbose ? " -v" : "",
  1878. recursive ? " -r" : "",
  1879. preserve ? " -p" : "",
  1880. targetshouldbedirectory ? " -d" : "", targ);
  1881. do_cmd(host, user, cmd);
  1882. sfree(cmd);
  1883. if (scp_source_setup(targ, targetshouldbedirectory))
  1884. return;
  1885. for (i = 0; i < argc - 1; i++) {
  1886. src = argv[i];
  1887. if (colon(src) != NULL) {
  1888. tell_user(stderr, "%s: Remote to remote not supported\n", src);
  1889. errs++;
  1890. continue;
  1891. }
  1892. wc_type = test_wildcard(src, 1);
  1893. if (wc_type == WCTYPE_NONEXISTENT) {
  1894. run_err("%s: No such file or directory", src);
  1895. continue;
  1896. } else if (wc_type == WCTYPE_FILENAME) {
  1897. source(src);
  1898. continue;
  1899. } else {
  1900. WildcardMatcher *wc;
  1901. char *filename;
  1902. wc = begin_wildcard_matching(src);
  1903. if (wc == NULL) {
  1904. run_err("%s: No such file or directory", src);
  1905. continue;
  1906. }
  1907. while ((filename = wildcard_get_filename(wc)) != NULL) {
  1908. source(filename);
  1909. sfree(filename);
  1910. }
  1911. finish_wildcard_matching(wc);
  1912. }
  1913. }
  1914. }
  1915. /*
  1916. * We will copy files from a remote server to the local machine.
  1917. */
  1918. static void tolocal(int argc, char *argv[])
  1919. {
  1920. char *src, *targ, *host, *user;
  1921. char *cmd;
  1922. if (argc != 2)
  1923. bump("More than one remote source not supported");
  1924. src = argv[0];
  1925. targ = argv[1];
  1926. /* Separate host from filename */
  1927. host = src;
  1928. src = colon(src);
  1929. if (src == NULL)
  1930. bump("Local to local copy not supported");
  1931. *src++ = '\0';
  1932. if (*src == '\0')
  1933. src = ".";
  1934. /* Substitute "." for empty filename */
  1935. /* Separate username and hostname */
  1936. user = host;
  1937. host = strrchr(host, '@');
  1938. if (host == NULL) {
  1939. host = user;
  1940. user = NULL;
  1941. } else {
  1942. *host++ = '\0';
  1943. if (*user == '\0')
  1944. user = NULL;
  1945. }
  1946. cmd = dupprintf("scp%s%s%s%s -f %s",
  1947. verbose ? " -v" : "",
  1948. recursive ? " -r" : "",
  1949. preserve ? " -p" : "",
  1950. targetshouldbedirectory ? " -d" : "", src);
  1951. do_cmd(host, user, cmd);
  1952. sfree(cmd);
  1953. if (scp_sink_setup(src, preserve, recursive))
  1954. return;
  1955. sink(targ, src);
  1956. }
  1957. /*
  1958. * We will issue a list command to get a remote directory.
  1959. */
  1960. static void get_dir_list(int argc, char *argv[])
  1961. {
  1962. char *src, *host, *user;
  1963. char *cmd, *p, *q;
  1964. char c;
  1965. src = argv[0];
  1966. /* Separate host from filename */
  1967. host = src;
  1968. src = colon(src);
  1969. if (src == NULL)
  1970. bump("Local file listing not supported");
  1971. *src++ = '\0';
  1972. if (*src == '\0')
  1973. src = ".";
  1974. /* Substitute "." for empty filename */
  1975. /* Separate username and hostname */
  1976. user = host;
  1977. host = strrchr(host, '@');
  1978. if (host == NULL) {
  1979. host = user;
  1980. user = NULL;
  1981. } else {
  1982. *host++ = '\0';
  1983. if (*user == '\0')
  1984. user = NULL;
  1985. }
  1986. cmd = snewn(4 * strlen(src) + 100, char);
  1987. strcpy(cmd, "ls -la '");
  1988. p = cmd + strlen(cmd);
  1989. for (q = src; *q; q++) {
  1990. if (*q == '\'') {
  1991. *p++ = '\'';
  1992. *p++ = '\\';
  1993. *p++ = '\'';
  1994. *p++ = '\'';
  1995. } else {
  1996. *p++ = *q;
  1997. }
  1998. }
  1999. *p++ = '\'';
  2000. *p = '\0';
  2001. do_cmd(host, user, cmd);
  2002. sfree(cmd);
  2003. if (using_sftp) {
  2004. scp_sftp_listdir(src);
  2005. } else {
  2006. while (ssh_scp_recv((unsigned char *) &c, 1) > 0)
  2007. tell_char(stdout, c);
  2008. }
  2009. }
  2010. /*
  2011. * Short description of parameters.
  2012. */
  2013. static void usage(void)
  2014. {
  2015. printf("PuTTY Secure Copy client\n");
  2016. printf("%s\n", ver);
  2017. printf("Usage: pscp [options] [user@]host:source target\n");
  2018. printf
  2019. (" pscp [options] source [source...] [user@]host:target\n");
  2020. printf(" pscp [options] -ls [user@]host:filespec\n");
  2021. printf("Options:\n");
  2022. printf(" -V print version information and exit\n");
  2023. printf(" -pgpfp print PGP key fingerprints and exit\n");
  2024. printf(" -p preserve file attributes\n");
  2025. printf(" -q quiet, don't show statistics\n");
  2026. printf(" -r copy directories recursively\n");
  2027. printf(" -v show verbose messages\n");
  2028. printf(" -load sessname Load settings from saved session\n");
  2029. printf(" -P port connect to specified port\n");
  2030. printf(" -l user connect with specified username\n");
  2031. printf(" -pw passw login with specified password\n");
  2032. printf(" -1 -2 force use of particular SSH protocol version\n");
  2033. printf(" -4 -6 force use of IPv4 or IPv6\n");
  2034. printf(" -C enable compression\n");
  2035. printf(" -i key private key file for authentication\n");
  2036. printf(" -noagent disable use of Pageant\n");
  2037. printf(" -agent enable use of Pageant\n");
  2038. printf(" -batch disable all interactive prompts\n");
  2039. printf(" -unsafe allow server-side wildcards (DANGEROUS)\n");
  2040. printf(" -sftp force use of SFTP protocol\n");
  2041. printf(" -scp force use of SCP protocol\n");
  2042. #if 0
  2043. /*
  2044. * -gui is an internal option, used by GUI front ends to get
  2045. * pscp to pass progress reports back to them. It's not an
  2046. * ordinary user-accessible option, so it shouldn't be part of
  2047. * the command-line help. The only people who need to know
  2048. * about it are programmers, and they can read the source.
  2049. */
  2050. printf
  2051. (" -gui hWnd GUI mode with the windows handle for receiving messages\n");
  2052. #endif
  2053. cleanup_exit(1);
  2054. }
  2055. void version(void)
  2056. {
  2057. printf("pscp: %s\n", ver);
  2058. cleanup_exit(1);
  2059. }
  2060. void cmdline_error(char *p, ...)
  2061. {
  2062. va_list ap;
  2063. fprintf(stderr, "pscp: ");
  2064. va_start(ap, p);
  2065. vfprintf(stderr, p, ap);
  2066. va_end(ap);
  2067. fprintf(stderr, "\n try typing just \"pscp\" for help\n");
  2068. exit(1);
  2069. }
  2070. /*
  2071. * Main program. (Called `psftp_main' because it gets called from
  2072. * *sftp.c; bit silly, I know, but it had to be called _something_.)
  2073. */
  2074. int psftp_main(int argc, char *argv[])
  2075. {
  2076. int i;
  2077. default_protocol = PROT_TELNET;
  2078. flags = FLAG_STDERR
  2079. #ifdef FLAG_SYNCAGENT
  2080. | FLAG_SYNCAGENT
  2081. #endif
  2082. ;
  2083. cmdline_tooltype = TOOLTYPE_FILETRANSFER;
  2084. sk_init();
  2085. /* Load Default Settings before doing anything else. */
  2086. conf = conf_new();
  2087. do_defaults(NULL, conf);
  2088. loaded_session = FALSE;
  2089. for (i = 1; i < argc; i++) {
  2090. int ret;
  2091. if (argv[i][0] != '-')
  2092. break;
  2093. ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, conf);
  2094. if (ret == -2) {
  2095. cmdline_error("option \"%s\" requires an argument", argv[i]);
  2096. } else if (ret == 2) {
  2097. i++; /* skip next argument */
  2098. } else if (ret == 1) {
  2099. /* We have our own verbosity in addition to `flags'. */
  2100. if (flags & FLAG_VERBOSE)
  2101. verbose = 1;
  2102. } else if (strcmp(argv[i], "-pgpfp") == 0) {
  2103. pgp_fingerprints();
  2104. return 1;
  2105. } else if (strcmp(argv[i], "-r") == 0) {
  2106. recursive = 1;
  2107. } else if (strcmp(argv[i], "-p") == 0) {
  2108. preserve = 1;
  2109. } else if (strcmp(argv[i], "-q") == 0) {
  2110. statistics = 0;
  2111. } else if (strcmp(argv[i], "-h") == 0 ||
  2112. strcmp(argv[i], "-?") == 0 ||
  2113. strcmp(argv[i], "--help") == 0) {
  2114. usage();
  2115. } else if (strcmp(argv[i], "-V") == 0 ||
  2116. strcmp(argv[i], "--version") == 0) {
  2117. version();
  2118. } else if (strcmp(argv[i], "-ls") == 0) {
  2119. list = 1;
  2120. } else if (strcmp(argv[i], "-batch") == 0) {
  2121. console_batch_mode = 1;
  2122. } else if (strcmp(argv[i], "-unsafe") == 0) {
  2123. scp_unsafe_mode = 1;
  2124. } else if (strcmp(argv[i], "-sftp") == 0) {
  2125. try_scp = 0; try_sftp = 1;
  2126. } else if (strcmp(argv[i], "-scp") == 0) {
  2127. try_scp = 1; try_sftp = 0;
  2128. } else if (strcmp(argv[i], "--") == 0) {
  2129. i++;
  2130. break;
  2131. } else {
  2132. cmdline_error("unknown option \"%s\"", argv[i]);
  2133. }
  2134. }
  2135. argc -= i;
  2136. argv += i;
  2137. back = NULL;
  2138. if (list) {
  2139. if (argc != 1)
  2140. usage();
  2141. get_dir_list(argc, argv);
  2142. } else {
  2143. if (argc < 2)
  2144. usage();
  2145. if (argc > 2)
  2146. targetshouldbedirectory = 1;
  2147. if (colon(argv[argc - 1]) != NULL)
  2148. toremote(argc, argv);
  2149. else
  2150. tolocal(argc, argv);
  2151. }
  2152. if (back != NULL && back->connected(backhandle)) {
  2153. char ch;
  2154. back->special(backhandle, TS_EOF);
  2155. sent_eof = TRUE;
  2156. ssh_scp_recv((unsigned char *) &ch, 1);
  2157. }
  2158. random_save_seed();
  2159. cmdline_cleanup();
  2160. console_provide_logctx(NULL);
  2161. back->free(backhandle);
  2162. backhandle = NULL;
  2163. back = NULL;
  2164. sk_cleanup();
  2165. return (errs == 0 ? 0 : 1);
  2166. }
  2167. /* end */