scp.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. /* Dropbear Note: This file is based on OpenSSH 4.3p2. Avoid unnecessary
  2. changes to simplify future updates */
  3. /*
  4. * scp - secure remote copy. This is basically patched BSD rcp which
  5. * uses ssh to do the data transfer (instead of using rcmd).
  6. *
  7. * NOTE: This version should NOT be suid root. (This uses ssh to
  8. * do the transfer and ssh has the necessary privileges.)
  9. *
  10. * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>
  11. *
  12. * As far as I am concerned, the code I have written for this software
  13. * can be used freely for any purpose. Any derived versions of this
  14. * software must be clearly marked as such, and if the derived work is
  15. * incompatible with the protocol description in the RFC file, it must be
  16. * called by a name other than "ssh" or "Secure Shell".
  17. */
  18. /*
  19. * Copyright (c) 1999 Theo de Raadt. All rights reserved.
  20. * Copyright (c) 1999 Aaron Campbell. All rights reserved.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the above copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  32. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  34. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  35. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  37. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  38. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  39. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  40. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. */
  42. /*
  43. * Parts from:
  44. *
  45. * Copyright (c) 1983, 1990, 1992, 1993, 1995
  46. * The Regents of the University of California. All rights reserved.
  47. *
  48. * Redistribution and use in source and binary forms, with or without
  49. * modification, are permitted provided that the following conditions
  50. * are met:
  51. * 1. Redistributions of source code must retain the above copyright
  52. * notice, this list of conditions and the following disclaimer.
  53. * 2. Redistributions in binary form must reproduce the above copyright
  54. * notice, this list of conditions and the following disclaimer in the
  55. * documentation and/or other materials provided with the distribution.
  56. * 3. Neither the name of the University nor the names of its contributors
  57. * may be used to endorse or promote products derived from this software
  58. * without specific prior written permission.
  59. *
  60. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  61. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  62. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  63. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  64. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  65. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  66. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  67. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  68. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  69. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  70. * SUCH DAMAGE.
  71. *
  72. */
  73. #include "includes.h"
  74. /*RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");*/
  75. #include "atomicio.h"
  76. #include "compat.h"
  77. #include "scpmisc.h"
  78. #include "progressmeter.h"
  79. void bwlimit(int);
  80. /* Struct for addargs */
  81. arglist args;
  82. /* Bandwidth limit */
  83. off_t limit_rate = 0;
  84. /* Name of current file being transferred. */
  85. char *curfile;
  86. /* This is set to non-zero to enable verbose mode. */
  87. int verbose_mode = 0;
  88. /* This is set to zero if the progressmeter is not desired. */
  89. int showprogress = 1;
  90. /* This is the program to execute for the secured connection. ("ssh" or -S) */
  91. char *ssh_program = DROPBEAR_PATH_SSH_PROGRAM;
  92. /* This is used to store the pid of ssh_program */
  93. pid_t do_cmd_pid = -1;
  94. static void
  95. killchild(int signo)
  96. {
  97. if (do_cmd_pid > 1) {
  98. kill(do_cmd_pid, signo ? signo : SIGTERM);
  99. waitpid(do_cmd_pid, NULL, 0);
  100. }
  101. if (signo)
  102. _exit(1);
  103. exit(1);
  104. }
  105. static int
  106. do_local_cmd(arglist *a)
  107. {
  108. u_int i;
  109. int status;
  110. pid_t pid;
  111. if (a->num == 0)
  112. fatal("do_local_cmd: no arguments");
  113. if (verbose_mode) {
  114. fprintf(stderr, "Executing:");
  115. for (i = 0; i < a->num; i++)
  116. fprintf(stderr, " %s", a->list[i]);
  117. fprintf(stderr, "\n");
  118. }
  119. #if DROPBEAR_VFORK
  120. pid = vfork();
  121. #else
  122. pid = fork();
  123. #endif
  124. if (pid == -1)
  125. fatal("do_local_cmd: fork: %s", strerror(errno));
  126. if (pid == 0) {
  127. execvp(a->list[0], a->list);
  128. perror(a->list[0]);
  129. #if DROPBEAR_VFORK
  130. _exit(1);
  131. #else
  132. exit(1);
  133. #endif
  134. }
  135. do_cmd_pid = pid;
  136. signal(SIGTERM, killchild);
  137. signal(SIGINT, killchild);
  138. signal(SIGHUP, killchild);
  139. while (waitpid(pid, &status, 0) == -1)
  140. if (errno != EINTR)
  141. fatal("do_local_cmd: waitpid: %s", strerror(errno));
  142. do_cmd_pid = -1;
  143. if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
  144. return (-1);
  145. return (0);
  146. }
  147. /*
  148. * This function executes the given command as the specified user on the
  149. * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
  150. * assigns the input and output file descriptors on success.
  151. */
  152. static void
  153. arg_setup(char *host, char *remuser, char *cmd)
  154. {
  155. replacearg(&args, 0, "%s", ssh_program);
  156. if (remuser != NULL)
  157. addargs(&args, "-l%s", remuser);
  158. addargs(&args, "%s", host);
  159. addargs(&args, "%s", cmd);
  160. }
  161. int
  162. do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
  163. {
  164. int pin[2], pout[2], reserved[2];
  165. if (verbose_mode)
  166. fprintf(stderr,
  167. "Executing: program %s host %s, user %s, command %s\n",
  168. ssh_program, host,
  169. remuser ? remuser : "(unspecified)", cmd);
  170. /*
  171. * Reserve two descriptors so that the real pipes won't get
  172. * descriptors 0 and 1 because that will screw up dup2 below.
  173. */
  174. pipe(reserved);
  175. /* Create a socket pair for communicating with ssh. */
  176. if (pipe(pin) < 0)
  177. fatal("pipe: %s", strerror(errno));
  178. if (pipe(pout) < 0)
  179. fatal("pipe: %s", strerror(errno));
  180. /* Free the reserved descriptors. */
  181. close(reserved[0]);
  182. close(reserved[1]);
  183. /* uClinux needs to build the args here before vforking,
  184. otherwise we do it later on. */
  185. #if DROPBEAR_VFORK
  186. arg_setup(host, remuser, cmd);
  187. #endif
  188. /* Fork a child to execute the command on the remote host using ssh. */
  189. #if DROPBEAR_VFORK
  190. do_cmd_pid = vfork();
  191. #else
  192. do_cmd_pid = fork();
  193. #endif
  194. if (do_cmd_pid == 0) {
  195. /* Child. */
  196. close(pin[1]);
  197. close(pout[0]);
  198. dup2(pin[0], 0);
  199. dup2(pout[1], 1);
  200. close(pin[0]);
  201. close(pout[1]);
  202. #if !DROPBEAR_VFORK
  203. arg_setup(host, remuser, cmd);
  204. #endif
  205. execvp(ssh_program, args.list);
  206. perror(ssh_program);
  207. #if DROPBEAR_VFORK
  208. _exit(1);
  209. #else
  210. exit(1);
  211. #endif
  212. } else if (do_cmd_pid == -1) {
  213. fatal("fork: %s", strerror(errno));
  214. }
  215. #if DROPBEAR_VFORK
  216. /* clean up command */
  217. /* pop cmd */
  218. xfree(args.list[args.num-1]);
  219. args.list[args.num-1]=NULL;
  220. args.num--;
  221. /* pop host */
  222. xfree(args.list[args.num-1]);
  223. args.list[args.num-1]=NULL;
  224. args.num--;
  225. /* pop user */
  226. if (remuser != NULL) {
  227. xfree(args.list[args.num-1]);
  228. args.list[args.num-1]=NULL;
  229. args.num--;
  230. }
  231. #endif
  232. /* Parent. Close the other side, and return the local side. */
  233. close(pin[0]);
  234. *fdout = pin[1];
  235. close(pout[1]);
  236. *fdin = pout[0];
  237. signal(SIGTERM, killchild);
  238. signal(SIGINT, killchild);
  239. signal(SIGHUP, killchild);
  240. return 0;
  241. }
  242. typedef struct {
  243. size_t cnt;
  244. char *buf;
  245. } BUF;
  246. BUF *allocbuf(BUF *, int, int);
  247. void lostconn(int);
  248. void nospace(void);
  249. int okname(char *);
  250. void run_err(const char *,...);
  251. void verifydir(char *);
  252. uid_t userid;
  253. int errs, remin, remout;
  254. int pflag, iamremote, iamrecursive, targetshouldbedirectory;
  255. #define CMDNEEDS 64
  256. char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
  257. int response(void);
  258. void rsource(char *, struct stat *);
  259. void sink(int, char *[]);
  260. void source(int, char *[]);
  261. void tolocal(int, char *[]);
  262. void toremote(char *, int, char *[]);
  263. void usage(void);
  264. #if defined(DBMULTI_scp) || !DROPBEAR_MULTI
  265. #if defined(DBMULTI_scp) && DROPBEAR_MULTI
  266. int scp_main(int argc, char **argv)
  267. #else
  268. int
  269. main(int argc, char **argv)
  270. #endif
  271. {
  272. int ch, fflag, tflag, status;
  273. double speed;
  274. char *targ, *endp;
  275. extern char *optarg;
  276. extern int optind;
  277. /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
  278. sanitise_stdfd();
  279. memset(&args, '\0', sizeof(args));
  280. args.list = NULL;
  281. addargs(&args, "%s", ssh_program);
  282. fflag = tflag = 0;
  283. while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
  284. switch (ch) {
  285. /* User-visible flags. */
  286. case '1':
  287. case '2':
  288. case '4':
  289. case '6':
  290. case 'C':
  291. addargs(&args, "-%c", ch);
  292. break;
  293. case 'o':
  294. case 'c':
  295. case 'i':
  296. case 'F':
  297. addargs(&args, "-%c%s", ch, optarg);
  298. break;
  299. case 'P':
  300. addargs(&args, "-p%s", optarg);
  301. break;
  302. case 'B':
  303. fprintf(stderr, "Note: -B option is disabled in this version of scp");
  304. break;
  305. case 'l':
  306. speed = strtod(optarg, &endp);
  307. if (speed <= 0 || *endp != '\0')
  308. usage();
  309. limit_rate = speed * 1024;
  310. break;
  311. case 'p':
  312. pflag = 1;
  313. break;
  314. case 'r':
  315. iamrecursive = 1;
  316. break;
  317. case 'S':
  318. ssh_program = xstrdup(optarg);
  319. break;
  320. case 'v':
  321. addargs(&args, "-v");
  322. verbose_mode = 1;
  323. break;
  324. case 'q':
  325. #ifdef PROGRESS_METER
  326. addargs(&args, "-q");
  327. showprogress = 0;
  328. #endif
  329. break;
  330. /* Server options. */
  331. case 'd':
  332. targetshouldbedirectory = 1;
  333. break;
  334. case 'f': /* "from" */
  335. iamremote = 1;
  336. fflag = 1;
  337. break;
  338. case 't': /* "to" */
  339. iamremote = 1;
  340. tflag = 1;
  341. #ifdef HAVE_CYGWIN
  342. setmode(0, O_BINARY);
  343. #endif
  344. break;
  345. default:
  346. usage();
  347. }
  348. argc -= optind;
  349. argv += optind;
  350. if (!isatty(STDERR_FILENO))
  351. showprogress = 0;
  352. remin = STDIN_FILENO;
  353. remout = STDOUT_FILENO;
  354. if (fflag) {
  355. /* Follow "protocol", send data. */
  356. (void) response();
  357. source(argc, argv);
  358. exit(errs != 0);
  359. }
  360. if (tflag) {
  361. /* Receive data. */
  362. sink(argc, argv);
  363. exit(errs != 0);
  364. }
  365. if (argc < 2)
  366. usage();
  367. if (argc > 2)
  368. targetshouldbedirectory = 1;
  369. remin = remout = -1;
  370. do_cmd_pid = -1;
  371. /* Command to be executed on remote system using "ssh". */
  372. (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
  373. verbose_mode ? " -v" : "",
  374. iamrecursive ? " -r" : "", pflag ? " -p" : "",
  375. targetshouldbedirectory ? " -d" : "");
  376. (void) signal(SIGPIPE, lostconn);
  377. if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
  378. toremote(targ, argc, argv);
  379. else {
  380. if (targetshouldbedirectory)
  381. verifydir(argv[argc - 1]);
  382. tolocal(argc, argv); /* Dest is local host. */
  383. }
  384. /*
  385. * Finally check the exit status of the ssh process, if one was forked
  386. * and no error has occurred yet
  387. */
  388. if (do_cmd_pid != -1 && errs == 0) {
  389. if (remin != -1)
  390. (void) close(remin);
  391. if (remout != -1)
  392. (void) close(remout);
  393. if (waitpid(do_cmd_pid, &status, 0) == -1)
  394. errs = 1;
  395. else {
  396. if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
  397. errs = 1;
  398. }
  399. }
  400. exit(errs != 0);
  401. }
  402. #endif /* DBMULTI_scp stuff */
  403. void
  404. toremote(char *targ, int argc, char **argv)
  405. {
  406. int i, len;
  407. char *bp, *host, *src, *suser, *thost, *tuser, *arg;
  408. arglist alist;
  409. memset(&alist, '\0', sizeof(alist));
  410. alist.list = NULL;
  411. *targ++ = 0;
  412. if (*targ == 0)
  413. targ = ".";
  414. arg = xstrdup(argv[argc - 1]);
  415. if ((thost = strrchr(arg, '@'))) {
  416. /* user@host */
  417. *thost++ = 0;
  418. tuser = arg;
  419. if (*tuser == '\0')
  420. tuser = NULL;
  421. } else {
  422. thost = arg;
  423. tuser = NULL;
  424. }
  425. if (tuser != NULL && !okname(tuser)) {
  426. xfree(arg);
  427. return;
  428. }
  429. for (i = 0; i < argc - 1; i++) {
  430. src = colon(argv[i]);
  431. if (src) { /* remote to remote */
  432. freeargs(&alist);
  433. addargs(&alist, "%s", ssh_program);
  434. if (verbose_mode)
  435. addargs(&alist, "-v");
  436. #if 0
  437. /* Disabled since dbclient won't understand them
  438. and scp works fine without them. */
  439. addargs(&alist, "-x");
  440. addargs(&alist, "-oClearAllForwardings yes");
  441. addargs(&alist, "-n");
  442. #endif
  443. *src++ = 0;
  444. if (*src == 0)
  445. src = ".";
  446. host = strrchr(argv[i], '@');
  447. if (host) {
  448. *host++ = 0;
  449. host = cleanhostname(host);
  450. suser = argv[i];
  451. if (*suser == '\0')
  452. continue; /* pretend there wasn't any @ at all */
  453. else if (!okname(suser))
  454. continue;
  455. addargs(&alist, "-l");
  456. addargs(&alist, "%s", suser);
  457. } else {
  458. host = cleanhostname(argv[i]);
  459. }
  460. addargs(&alist, "%s", host);
  461. addargs(&alist, "%s", cmd);
  462. addargs(&alist, "%s", src);
  463. addargs(&alist, "%s%s%s:%s",
  464. tuser ? tuser : "", tuser ? "@" : "",
  465. thost, targ);
  466. if (do_local_cmd(&alist) != 0)
  467. errs = 1;
  468. } else { /* local to remote */
  469. if (remin == -1) {
  470. len = strlen(targ) + CMDNEEDS + 20;
  471. bp = xmalloc(len);
  472. (void) snprintf(bp, len, "%s -t %s", cmd, targ);
  473. host = cleanhostname(thost);
  474. if (do_cmd(host, tuser, bp, &remin, &remout) < 0)
  475. exit(1);
  476. if (response() < 0)
  477. exit(1);
  478. (void) xfree(bp);
  479. }
  480. source(1, argv + i);
  481. }
  482. }
  483. }
  484. void
  485. tolocal(int argc, char **argv)
  486. {
  487. int i, len;
  488. char *bp, *host, *src, *suser;
  489. arglist alist;
  490. memset(&alist, '\0', sizeof(alist));
  491. alist.list = NULL;
  492. for (i = 0; i < argc - 1; i++) {
  493. if (!(src = colon(argv[i]))) { /* Local to local. */
  494. freeargs(&alist);
  495. addargs(&alist, "%s", _PATH_CP);
  496. if (iamrecursive)
  497. addargs(&alist, "-r");
  498. if (pflag)
  499. addargs(&alist, "-p");
  500. addargs(&alist, "%s", argv[i]);
  501. addargs(&alist, "%s", argv[argc-1]);
  502. if (do_local_cmd(&alist))
  503. ++errs;
  504. continue;
  505. }
  506. *src++ = 0;
  507. if (*src == 0)
  508. src = ".";
  509. if ((host = strrchr(argv[i], '@')) == NULL) {
  510. host = argv[i];
  511. suser = NULL;
  512. } else {
  513. *host++ = 0;
  514. suser = argv[i];
  515. if (*suser == '\0')
  516. suser = NULL;
  517. }
  518. host = cleanhostname(host);
  519. len = strlen(src) + CMDNEEDS + 20;
  520. bp = xmalloc(len);
  521. (void) snprintf(bp, len, "%s -f %s", cmd, src);
  522. if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
  523. (void) xfree(bp);
  524. ++errs;
  525. continue;
  526. }
  527. xfree(bp);
  528. sink(1, argv + argc - 1);
  529. (void) close(remin);
  530. remin = remout = -1;
  531. }
  532. }
  533. void
  534. source(int argc, char **argv)
  535. {
  536. struct stat stb;
  537. static BUF buffer;
  538. BUF *bp;
  539. off_t i, amt, statbytes;
  540. size_t result;
  541. int fd = -1, haderr, indx;
  542. char *last, *name, buf[2048];
  543. int len;
  544. for (indx = 0; indx < argc; ++indx) {
  545. name = argv[indx];
  546. statbytes = 0;
  547. len = strlen(name);
  548. while (len > 1 && name[len-1] == '/')
  549. name[--len] = '\0';
  550. if (strchr(name, '\n') != NULL) {
  551. run_err("%s: skipping, filename contains a newline",
  552. name);
  553. goto next;
  554. }
  555. if ((fd = open(name, O_RDONLY, 0)) < 0)
  556. goto syserr;
  557. if (fstat(fd, &stb) < 0) {
  558. syserr: run_err("%s: %s", name, strerror(errno));
  559. goto next;
  560. }
  561. switch (stb.st_mode & S_IFMT) {
  562. case S_IFREG:
  563. break;
  564. case S_IFDIR:
  565. if (iamrecursive) {
  566. rsource(name, &stb);
  567. goto next;
  568. }
  569. /* FALLTHROUGH */
  570. default:
  571. run_err("%s: not a regular file", name);
  572. goto next;
  573. }
  574. if ((last = strrchr(name, '/')) == NULL)
  575. last = name;
  576. else
  577. ++last;
  578. curfile = last;
  579. if (pflag) {
  580. /*
  581. * Make it compatible with possible future
  582. * versions expecting microseconds.
  583. */
  584. (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
  585. (u_long) stb.st_mtime,
  586. (u_long) stb.st_atime);
  587. (void) atomicio(vwrite, remout, buf, strlen(buf));
  588. if (response() < 0)
  589. goto next;
  590. }
  591. #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
  592. snprintf(buf, sizeof buf, "C%04o %lld %s\n",
  593. (u_int) (stb.st_mode & FILEMODEMASK),
  594. (long long)stb.st_size, last);
  595. if (verbose_mode) {
  596. fprintf(stderr, "Sending file modes: %s", buf);
  597. }
  598. (void) atomicio(vwrite, remout, buf, strlen(buf));
  599. if (response() < 0)
  600. goto next;
  601. if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
  602. next: if (fd != -1) {
  603. (void) close(fd);
  604. fd = -1;
  605. }
  606. continue;
  607. }
  608. #ifdef PROGRESS_METER
  609. if (showprogress)
  610. start_progress_meter(curfile, stb.st_size, &statbytes);
  611. #endif
  612. /* Keep writing after an error so that we stay sync'd up. */
  613. for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
  614. amt = bp->cnt;
  615. if (i + amt > stb.st_size)
  616. amt = stb.st_size - i;
  617. if (!haderr) {
  618. result = atomicio(read, fd, bp->buf, amt);
  619. if (result != amt)
  620. haderr = errno;
  621. }
  622. if (haderr)
  623. (void) atomicio(vwrite, remout, bp->buf, amt);
  624. else {
  625. result = atomicio(vwrite, remout, bp->buf, amt);
  626. if (result != amt)
  627. haderr = errno;
  628. statbytes += result;
  629. }
  630. if (limit_rate)
  631. bwlimit(amt);
  632. }
  633. #ifdef PROGRESS_METER
  634. if (showprogress)
  635. stop_progress_meter();
  636. #endif
  637. if (fd != -1) {
  638. if (close(fd) < 0 && !haderr)
  639. haderr = errno;
  640. fd = -1;
  641. }
  642. if (!haderr)
  643. (void) atomicio(vwrite, remout, "", 1);
  644. else
  645. run_err("%s: %s", name, strerror(haderr));
  646. (void) response();
  647. }
  648. }
  649. void
  650. rsource(char *name, struct stat *statp)
  651. {
  652. DIR *dirp;
  653. struct dirent *dp;
  654. char *last, *vect[1], path[1100];
  655. if (!(dirp = opendir(name))) {
  656. run_err("%s: %s", name, strerror(errno));
  657. return;
  658. }
  659. last = strrchr(name, '/');
  660. if (last == 0)
  661. last = name;
  662. else
  663. last++;
  664. if (pflag) {
  665. (void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n",
  666. (u_long) statp->st_mtime,
  667. (u_long) statp->st_atime);
  668. (void) atomicio(vwrite, remout, path, strlen(path));
  669. if (response() < 0) {
  670. closedir(dirp);
  671. return;
  672. }
  673. }
  674. (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
  675. (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
  676. if (verbose_mode)
  677. fprintf(stderr, "Entering directory: %s", path);
  678. (void) atomicio(vwrite, remout, path, strlen(path));
  679. if (response() < 0) {
  680. closedir(dirp);
  681. return;
  682. }
  683. while ((dp = readdir(dirp)) != NULL) {
  684. if (dp->d_ino == 0)
  685. continue;
  686. if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  687. continue;
  688. if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
  689. run_err("%s/%s: name too long", name, dp->d_name);
  690. continue;
  691. }
  692. (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
  693. vect[0] = path;
  694. source(1, vect);
  695. }
  696. (void) closedir(dirp);
  697. (void) atomicio(vwrite, remout, "E\n", 2);
  698. (void) response();
  699. }
  700. void
  701. bwlimit(int amount)
  702. {
  703. static struct timeval bwstart, bwend;
  704. static int lamt = 0, thresh = 16384;
  705. uint64_t waitlen;
  706. struct timespec ts, rm;
  707. if (!timerisset(&bwstart)) {
  708. gettimeofday(&bwstart, NULL);
  709. return;
  710. }
  711. lamt += amount;
  712. if (lamt < thresh)
  713. return;
  714. gettimeofday(&bwend, NULL);
  715. timersub(&bwend, &bwstart, &bwend);
  716. if (!timerisset(&bwend))
  717. return;
  718. lamt *= 8;
  719. waitlen = (double)1000000L * lamt / limit_rate;
  720. bwstart.tv_sec = waitlen / 1000000L;
  721. bwstart.tv_usec = waitlen % 1000000L;
  722. if (timercmp(&bwstart, &bwend, >)) {
  723. timersub(&bwstart, &bwend, &bwend);
  724. /* Adjust the wait time */
  725. if (bwend.tv_sec) {
  726. thresh /= 2;
  727. if (thresh < 2048)
  728. thresh = 2048;
  729. } else if (bwend.tv_usec < 100) {
  730. thresh *= 2;
  731. if (thresh > 32768)
  732. thresh = 32768;
  733. }
  734. TIMEVAL_TO_TIMESPEC(&bwend, &ts);
  735. while (nanosleep(&ts, &rm) == -1) {
  736. if (errno != EINTR)
  737. break;
  738. ts = rm;
  739. }
  740. }
  741. lamt = 0;
  742. gettimeofday(&bwstart, NULL);
  743. }
  744. void
  745. sink(int argc, char **argv)
  746. {
  747. static BUF buffer;
  748. struct stat stb;
  749. enum {
  750. YES, NO, DISPLAYED
  751. } wrerr;
  752. BUF *bp;
  753. off_t i;
  754. size_t j, count;
  755. int amt, exists, first, mask, mode, ofd, omode;
  756. off_t size, statbytes;
  757. int setimes, targisdir, wrerrno = 0;
  758. char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
  759. struct timeval tv[2];
  760. #define atime tv[0]
  761. #define mtime tv[1]
  762. #define SCREWUP(str) do { why = str; goto screwup; } while (0)
  763. setimes = targisdir = 0;
  764. mask = umask(0);
  765. if (!pflag)
  766. (void) umask(mask);
  767. if (argc != 1) {
  768. run_err("ambiguous target");
  769. exit(1);
  770. }
  771. targ = *argv;
  772. if (targetshouldbedirectory)
  773. verifydir(targ);
  774. (void) atomicio(vwrite, remout, "", 1);
  775. if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
  776. targisdir = 1;
  777. for (first = 1;; first = 0) {
  778. cp = buf;
  779. if (atomicio(read, remin, cp, 1) != 1)
  780. return;
  781. if (*cp++ == '\n')
  782. SCREWUP("unexpected <newline>");
  783. do {
  784. if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
  785. SCREWUP("lost connection");
  786. *cp++ = ch;
  787. } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
  788. *cp = 0;
  789. if (verbose_mode)
  790. fprintf(stderr, "Sink: %s", buf);
  791. if (buf[0] == '\01' || buf[0] == '\02') {
  792. if (iamremote == 0)
  793. (void) atomicio(vwrite, STDERR_FILENO,
  794. buf + 1, strlen(buf + 1));
  795. if (buf[0] == '\02')
  796. exit(1);
  797. ++errs;
  798. continue;
  799. }
  800. if (buf[0] == 'E') {
  801. (void) atomicio(vwrite, remout, "", 1);
  802. return;
  803. }
  804. if (ch == '\n')
  805. *--cp = 0;
  806. cp = buf;
  807. if (*cp == 'T') {
  808. setimes++;
  809. cp++;
  810. mtime.tv_sec = strtol(cp, &cp, 10);
  811. if (!cp || *cp++ != ' ')
  812. SCREWUP("mtime.sec not delimited");
  813. mtime.tv_usec = strtol(cp, &cp, 10);
  814. if (!cp || *cp++ != ' ')
  815. SCREWUP("mtime.usec not delimited");
  816. atime.tv_sec = strtol(cp, &cp, 10);
  817. if (!cp || *cp++ != ' ')
  818. SCREWUP("atime.sec not delimited");
  819. atime.tv_usec = strtol(cp, &cp, 10);
  820. if (!cp || *cp++ != '\0')
  821. SCREWUP("atime.usec not delimited");
  822. (void) atomicio(vwrite, remout, "", 1);
  823. continue;
  824. }
  825. if (*cp != 'C' && *cp != 'D') {
  826. /*
  827. * Check for the case "rcp remote:foo\* local:bar".
  828. * In this case, the line "No match." can be returned
  829. * by the shell before the rcp command on the remote is
  830. * executed so the ^Aerror_message convention isn't
  831. * followed.
  832. */
  833. if (first) {
  834. run_err("%s", cp);
  835. exit(1);
  836. }
  837. SCREWUP("expected control record");
  838. }
  839. mode = 0;
  840. for (++cp; cp < buf + 5; cp++) {
  841. if (*cp < '0' || *cp > '7')
  842. SCREWUP("bad mode");
  843. mode = (mode << 3) | (*cp - '0');
  844. }
  845. if (*cp++ != ' ')
  846. SCREWUP("mode not delimited");
  847. for (size = 0; isdigit(*cp);)
  848. size = size * 10 + (*cp++ - '0');
  849. if (*cp++ != ' ')
  850. SCREWUP("size not delimited");
  851. if (*cp == '\0' || strchr(cp, '/') != NULL ||
  852. strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
  853. run_err("error: unexpected filename: %s", cp);
  854. exit(1);
  855. }
  856. if (targisdir) {
  857. static char *namebuf = NULL;
  858. static size_t cursize = 0;
  859. size_t need;
  860. need = strlen(targ) + strlen(cp) + 250;
  861. if (need > cursize) {
  862. if (namebuf)
  863. xfree(namebuf);
  864. namebuf = xmalloc(need);
  865. cursize = need;
  866. }
  867. (void) snprintf(namebuf, need, "%s%s%s", targ,
  868. strcmp(targ, "/") ? "/" : "", cp);
  869. np = namebuf;
  870. } else
  871. np = targ;
  872. curfile = cp;
  873. exists = stat(np, &stb) == 0;
  874. if (buf[0] == 'D') {
  875. int mod_flag = pflag;
  876. if (!iamrecursive)
  877. SCREWUP("received directory without -r");
  878. if (exists) {
  879. if (!S_ISDIR(stb.st_mode)) {
  880. errno = ENOTDIR;
  881. goto bad;
  882. }
  883. if (pflag)
  884. (void) chmod(np, mode);
  885. } else {
  886. /* Handle copying from a read-only
  887. directory */
  888. mod_flag = 1;
  889. if (mkdir(np, mode | S_IRWXU) < 0)
  890. goto bad;
  891. }
  892. vect[0] = xstrdup(np);
  893. sink(1, vect);
  894. if (setimes) {
  895. setimes = 0;
  896. if (utimes(vect[0], tv) < 0)
  897. run_err("%s: set times: %s",
  898. vect[0], strerror(errno));
  899. }
  900. if (mod_flag)
  901. (void) chmod(vect[0], mode);
  902. if (vect[0])
  903. xfree(vect[0]);
  904. continue;
  905. }
  906. omode = mode;
  907. mode |= S_IWUSR;
  908. if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
  909. bad: run_err("%s: %s", np, strerror(errno));
  910. continue;
  911. }
  912. (void) atomicio(vwrite, remout, "", 1);
  913. if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
  914. (void) close(ofd);
  915. continue;
  916. }
  917. cp = bp->buf;
  918. wrerr = NO;
  919. statbytes = 0;
  920. #ifdef PROGRESS_METER
  921. if (showprogress)
  922. start_progress_meter(curfile, size, &statbytes);
  923. #endif
  924. for (count = i = 0; i < size; i += 4096) {
  925. amt = 4096;
  926. if (i + amt > size)
  927. amt = size - i;
  928. count += amt;
  929. do {
  930. j = atomicio(read, remin, cp, amt);
  931. if (j == 0) {
  932. run_err("%s", j ? strerror(errno) :
  933. "dropped connection");
  934. exit(1);
  935. }
  936. amt -= j;
  937. cp += j;
  938. statbytes += j;
  939. } while (amt > 0);
  940. if (limit_rate)
  941. bwlimit(4096);
  942. if (count == bp->cnt) {
  943. /* Keep reading so we stay sync'd up. */
  944. if (wrerr == NO) {
  945. if (atomicio(vwrite, ofd, bp->buf,
  946. count) != count) {
  947. wrerr = YES;
  948. wrerrno = errno;
  949. }
  950. }
  951. count = 0;
  952. cp = bp->buf;
  953. }
  954. }
  955. #ifdef PROGRESS_METER
  956. if (showprogress)
  957. stop_progress_meter();
  958. #endif
  959. if (count != 0 && wrerr == NO &&
  960. atomicio(vwrite, ofd, bp->buf, count) != count) {
  961. wrerr = YES;
  962. wrerrno = errno;
  963. }
  964. if (wrerr == NO && ftruncate(ofd, size) != 0) {
  965. run_err("%s: truncate: %s", np, strerror(errno));
  966. wrerr = DISPLAYED;
  967. }
  968. if (pflag) {
  969. if (exists || omode != mode)
  970. #ifdef HAVE_FCHMOD
  971. if (fchmod(ofd, omode)) {
  972. #else /* HAVE_FCHMOD */
  973. if (chmod(np, omode)) {
  974. #endif /* HAVE_FCHMOD */
  975. run_err("%s: set mode: %s",
  976. np, strerror(errno));
  977. wrerr = DISPLAYED;
  978. }
  979. } else {
  980. if (!exists && omode != mode)
  981. #ifdef HAVE_FCHMOD
  982. if (fchmod(ofd, omode & ~mask)) {
  983. #else /* HAVE_FCHMOD */
  984. if (chmod(np, omode & ~mask)) {
  985. #endif /* HAVE_FCHMOD */
  986. run_err("%s: set mode: %s",
  987. np, strerror(errno));
  988. wrerr = DISPLAYED;
  989. }
  990. }
  991. if (close(ofd) == -1) {
  992. wrerr = YES;
  993. wrerrno = errno;
  994. }
  995. (void) response();
  996. if (setimes && wrerr == NO) {
  997. setimes = 0;
  998. if (utimes(np, tv) < 0) {
  999. run_err("%s: set times: %s",
  1000. np, strerror(errno));
  1001. wrerr = DISPLAYED;
  1002. }
  1003. }
  1004. switch (wrerr) {
  1005. case YES:
  1006. run_err("%s: %s", np, strerror(wrerrno));
  1007. break;
  1008. case NO:
  1009. (void) atomicio(vwrite, remout, "", 1);
  1010. break;
  1011. case DISPLAYED:
  1012. break;
  1013. }
  1014. }
  1015. screwup:
  1016. run_err("protocol error: %s", why);
  1017. exit(1);
  1018. }
  1019. int
  1020. response(void)
  1021. {
  1022. char ch, *cp, resp, rbuf[2048];
  1023. if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
  1024. lostconn(0);
  1025. cp = rbuf;
  1026. switch (resp) {
  1027. case 0: /* ok */
  1028. return (0);
  1029. default:
  1030. *cp++ = resp;
  1031. /* FALLTHROUGH */
  1032. case 1: /* error, followed by error msg */
  1033. case 2: /* fatal error, "" */
  1034. do {
  1035. if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
  1036. lostconn(0);
  1037. *cp++ = ch;
  1038. } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
  1039. if (!iamremote)
  1040. (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf);
  1041. ++errs;
  1042. if (resp == 1)
  1043. return (-1);
  1044. exit(1);
  1045. }
  1046. /* NOTREACHED */
  1047. }
  1048. void
  1049. usage(void)
  1050. {
  1051. (void) fprintf(stderr,
  1052. "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
  1053. " [-l limit] [-P port] [-S program]\n"
  1054. " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
  1055. exit(1);
  1056. }
  1057. void
  1058. run_err(const char *fmt,...)
  1059. {
  1060. static FILE *fp = NULL;
  1061. va_list ap;
  1062. ++errs;
  1063. if (fp == NULL && !(fp = fdopen(remout, "w")))
  1064. return;
  1065. (void) fprintf(fp, "%c", 0x01);
  1066. (void) fprintf(fp, "scp: ");
  1067. va_start(ap, fmt);
  1068. (void) vfprintf(fp, fmt, ap);
  1069. va_end(ap);
  1070. (void) fprintf(fp, "\n");
  1071. (void) fflush(fp);
  1072. if (!iamremote) {
  1073. va_start(ap, fmt);
  1074. vfprintf(stderr, fmt, ap);
  1075. va_end(ap);
  1076. fprintf(stderr, "\n");
  1077. }
  1078. }
  1079. void
  1080. verifydir(char *cp)
  1081. {
  1082. struct stat stb;
  1083. if (!stat(cp, &stb)) {
  1084. if (S_ISDIR(stb.st_mode))
  1085. return;
  1086. errno = ENOTDIR;
  1087. }
  1088. run_err("%s: %s", cp, strerror(errno));
  1089. killchild(0);
  1090. }
  1091. int
  1092. okname(char *cp0)
  1093. {
  1094. int c;
  1095. char *cp;
  1096. cp = cp0;
  1097. do {
  1098. c = (int)*cp;
  1099. if (c & 0200)
  1100. goto bad;
  1101. if (!isalpha(c) && !isdigit(c)) {
  1102. switch (c) {
  1103. case '\'':
  1104. case '"':
  1105. case '`':
  1106. case ' ':
  1107. case '#':
  1108. goto bad;
  1109. default:
  1110. break;
  1111. }
  1112. }
  1113. } while (*++cp);
  1114. return (1);
  1115. bad: fprintf(stderr, "%s: invalid user name\n", cp0);
  1116. return (0);
  1117. }
  1118. BUF *
  1119. allocbuf(BUF *bp, int fd, int blksize)
  1120. {
  1121. size_t size;
  1122. #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  1123. struct stat stb;
  1124. if (fstat(fd, &stb) < 0) {
  1125. run_err("fstat: %s", strerror(errno));
  1126. return (0);
  1127. }
  1128. size = roundup(stb.st_blksize, blksize);
  1129. if (size == 0)
  1130. size = blksize;
  1131. #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
  1132. size = blksize;
  1133. #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
  1134. if (bp->cnt >= size)
  1135. return (bp);
  1136. if (bp->buf == NULL)
  1137. bp->buf = xmalloc(size);
  1138. else
  1139. bp->buf = xrealloc(bp->buf, size);
  1140. memset(bp->buf, 0, size);
  1141. bp->cnt = size;
  1142. return (bp);
  1143. }
  1144. void
  1145. lostconn(int signo)
  1146. {
  1147. if (!iamremote)
  1148. write(STDERR_FILENO, "lost connection\n", 16);
  1149. if (signo)
  1150. _exit(1);
  1151. else
  1152. exit(1);
  1153. }