/usr/src/cmd/ssh/sftp-server/sftp-server.c

https://bitbucket.org/illumos/illumos-gate/ · C · 1364 lines · 1159 code · 146 blank · 59 comment · 216 complexity · 7f36a0bd72cd14b8ecdad395c380073c MD5 · raw file

  1. /*
  2. * Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /* $OpenBSD: sftp-server.c,v 1.71 2007/01/03 07:22:36 stevesk Exp $ */
  17. #include "includes.h"
  18. #include <sys/types.h>
  19. #include <sys/param.h>
  20. #include <sys/stat.h>
  21. #ifdef HAVE_SYS_TIME_H
  22. # include <sys/time.h>
  23. #endif
  24. #include <dirent.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <pwd.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <pwd.h>
  32. #include <time.h>
  33. #include <unistd.h>
  34. #include <stdarg.h>
  35. #include "xmalloc.h"
  36. #include "buffer.h"
  37. #include "bufaux.h"
  38. #include "log.h"
  39. #include "misc.h"
  40. #include "uidswap.h"
  41. #include "sftp.h"
  42. #include "sftp-common.h"
  43. #ifdef HAVE___PROGNAME
  44. extern char *__progname;
  45. #else
  46. char *__progname;
  47. #endif
  48. /* helper */
  49. #define get_int64() buffer_get_int64(&iqueue);
  50. #define get_int() buffer_get_int(&iqueue);
  51. #define get_string(lenp) buffer_get_string(&iqueue, lenp);
  52. void cleanup_exit(int i);
  53. /* Our verbosity */
  54. LogLevel log_level = SYSLOG_LEVEL_ERROR;
  55. /* Our client */
  56. struct passwd *pw = NULL;
  57. char *client_addr = NULL;
  58. /* input and output queue */
  59. Buffer iqueue;
  60. Buffer oqueue;
  61. /* Version of client */
  62. int version;
  63. /* portable attributes, etc. */
  64. typedef struct Stat Stat;
  65. struct Stat {
  66. char *name;
  67. char *long_name;
  68. Attrib attrib;
  69. };
  70. static int
  71. errno_to_portable(int unixerrno)
  72. {
  73. int ret = 0;
  74. switch (unixerrno) {
  75. case 0:
  76. ret = SSH2_FX_OK;
  77. break;
  78. case ENOENT:
  79. case ENOTDIR:
  80. case EBADF:
  81. case ELOOP:
  82. ret = SSH2_FX_NO_SUCH_FILE;
  83. break;
  84. case EPERM:
  85. case EACCES:
  86. case EFAULT:
  87. ret = SSH2_FX_PERMISSION_DENIED;
  88. break;
  89. case ENAMETOOLONG:
  90. case EINVAL:
  91. ret = SSH2_FX_BAD_MESSAGE;
  92. break;
  93. default:
  94. ret = SSH2_FX_FAILURE;
  95. break;
  96. }
  97. return ret;
  98. }
  99. static int
  100. flags_from_portable(int pflags)
  101. {
  102. int flags = 0;
  103. if ((pflags & SSH2_FXF_READ) &&
  104. (pflags & SSH2_FXF_WRITE)) {
  105. flags = O_RDWR;
  106. } else if (pflags & SSH2_FXF_READ) {
  107. flags = O_RDONLY;
  108. } else if (pflags & SSH2_FXF_WRITE) {
  109. flags = O_WRONLY;
  110. }
  111. if (pflags & SSH2_FXF_CREAT)
  112. flags |= O_CREAT;
  113. if (pflags & SSH2_FXF_TRUNC)
  114. flags |= O_TRUNC;
  115. if (pflags & SSH2_FXF_EXCL)
  116. flags |= O_EXCL;
  117. return flags;
  118. }
  119. static const char *
  120. string_from_portable(int pflags)
  121. {
  122. static char ret[128];
  123. *ret = '\0';
  124. #define PAPPEND(str) { \
  125. if (*ret != '\0') \
  126. strlcat(ret, ",", sizeof(ret)); \
  127. strlcat(ret, str, sizeof(ret)); \
  128. }
  129. if (pflags & SSH2_FXF_READ)
  130. PAPPEND("READ")
  131. if (pflags & SSH2_FXF_WRITE)
  132. PAPPEND("WRITE")
  133. if (pflags & SSH2_FXF_CREAT)
  134. PAPPEND("CREATE")
  135. if (pflags & SSH2_FXF_TRUNC)
  136. PAPPEND("TRUNCATE")
  137. if (pflags & SSH2_FXF_EXCL)
  138. PAPPEND("EXCL")
  139. return ret;
  140. }
  141. static Attrib *
  142. get_attrib(void)
  143. {
  144. return decode_attrib(&iqueue);
  145. }
  146. /* handle handles */
  147. typedef struct Handle Handle;
  148. struct Handle {
  149. int use;
  150. DIR *dirp;
  151. int fd;
  152. char *name;
  153. u_int64_t bytes_read, bytes_write;
  154. };
  155. enum {
  156. HANDLE_UNUSED,
  157. HANDLE_DIR,
  158. HANDLE_FILE
  159. };
  160. Handle handles[100];
  161. static void
  162. handle_init(void)
  163. {
  164. u_int i;
  165. for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
  166. handles[i].use = HANDLE_UNUSED;
  167. }
  168. static int
  169. handle_new(int use, const char *name, int fd, DIR *dirp)
  170. {
  171. u_int i;
  172. for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) {
  173. if (handles[i].use == HANDLE_UNUSED) {
  174. handles[i].use = use;
  175. handles[i].dirp = dirp;
  176. handles[i].fd = fd;
  177. handles[i].name = xstrdup(name);
  178. handles[i].bytes_read = handles[i].bytes_write = 0;
  179. return i;
  180. }
  181. }
  182. return -1;
  183. }
  184. static int
  185. handle_is_ok(int i, int type)
  186. {
  187. return i >= 0 && (u_int)i < sizeof(handles)/sizeof(Handle) &&
  188. handles[i].use == type;
  189. }
  190. static int
  191. handle_to_string(int handle, char **stringp, int *hlenp)
  192. {
  193. if (stringp == NULL || hlenp == NULL)
  194. return -1;
  195. *stringp = xmalloc(sizeof(int32_t));
  196. put_u32(*stringp, handle);
  197. *hlenp = sizeof(int32_t);
  198. return 0;
  199. }
  200. static int
  201. handle_from_string(const char *handle, u_int hlen)
  202. {
  203. int val;
  204. if (hlen != sizeof(int32_t))
  205. return -1;
  206. val = get_u32(handle);
  207. if (handle_is_ok(val, HANDLE_FILE) ||
  208. handle_is_ok(val, HANDLE_DIR))
  209. return val;
  210. return -1;
  211. }
  212. static char *
  213. handle_to_name(int handle)
  214. {
  215. if (handle_is_ok(handle, HANDLE_DIR)||
  216. handle_is_ok(handle, HANDLE_FILE))
  217. return handles[handle].name;
  218. return NULL;
  219. }
  220. static DIR *
  221. handle_to_dir(int handle)
  222. {
  223. if (handle_is_ok(handle, HANDLE_DIR))
  224. return handles[handle].dirp;
  225. return NULL;
  226. }
  227. static int
  228. handle_to_fd(int handle)
  229. {
  230. if (handle_is_ok(handle, HANDLE_FILE))
  231. return handles[handle].fd;
  232. return -1;
  233. }
  234. static void
  235. handle_update_read(int handle, ssize_t bytes)
  236. {
  237. if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
  238. handles[handle].bytes_read += bytes;
  239. }
  240. static void
  241. handle_update_write(int handle, ssize_t bytes)
  242. {
  243. if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
  244. handles[handle].bytes_write += bytes;
  245. }
  246. static u_int64_t
  247. handle_bytes_read(int handle)
  248. {
  249. if (handle_is_ok(handle, HANDLE_FILE))
  250. return (handles[handle].bytes_read);
  251. return 0;
  252. }
  253. static u_int64_t
  254. handle_bytes_write(int handle)
  255. {
  256. if (handle_is_ok(handle, HANDLE_FILE))
  257. return (handles[handle].bytes_write);
  258. return 0;
  259. }
  260. static int
  261. handle_close(int handle)
  262. {
  263. int ret = -1;
  264. if (handle_is_ok(handle, HANDLE_FILE)) {
  265. ret = close(handles[handle].fd);
  266. handles[handle].use = HANDLE_UNUSED;
  267. xfree(handles[handle].name);
  268. } else if (handle_is_ok(handle, HANDLE_DIR)) {
  269. ret = closedir(handles[handle].dirp);
  270. handles[handle].use = HANDLE_UNUSED;
  271. xfree(handles[handle].name);
  272. } else {
  273. errno = ENOENT;
  274. }
  275. return ret;
  276. }
  277. static void
  278. handle_log_close(int handle, char *emsg)
  279. {
  280. if (handle_is_ok(handle, HANDLE_FILE)) {
  281. log("%s%sclose \"%s\" bytes read %llu written %llu",
  282. emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
  283. handle_to_name(handle),
  284. (unsigned long long)handle_bytes_read(handle),
  285. (unsigned long long)handle_bytes_write(handle));
  286. } else {
  287. log("%s%sclosedir \"%s\"",
  288. emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
  289. handle_to_name(handle));
  290. }
  291. }
  292. static void
  293. handle_log_exit(void)
  294. {
  295. u_int i;
  296. for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
  297. if (handles[i].use != HANDLE_UNUSED)
  298. handle_log_close(i, "forced");
  299. }
  300. static int
  301. get_handle(void)
  302. {
  303. char *handle;
  304. int val = -1;
  305. u_int hlen;
  306. handle = get_string(&hlen);
  307. if (hlen < 256)
  308. val = handle_from_string(handle, hlen);
  309. xfree(handle);
  310. return val;
  311. }
  312. /* send replies */
  313. static void
  314. send_msg(Buffer *m)
  315. {
  316. int mlen = buffer_len(m);
  317. buffer_put_int(&oqueue, mlen);
  318. buffer_append(&oqueue, buffer_ptr(m), mlen);
  319. buffer_consume(m, mlen);
  320. }
  321. static const char *
  322. status_to_message(u_int32_t status)
  323. {
  324. const char *status_messages[] = {
  325. "Success", /* SSH_FX_OK */
  326. "End of file", /* SSH_FX_EOF */
  327. "No such file", /* SSH_FX_NO_SUCH_FILE */
  328. "Permission denied", /* SSH_FX_PERMISSION_DENIED */
  329. "Failure", /* SSH_FX_FAILURE */
  330. "Bad message", /* SSH_FX_BAD_MESSAGE */
  331. "No connection", /* SSH_FX_NO_CONNECTION */
  332. "Connection lost", /* SSH_FX_CONNECTION_LOST */
  333. "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
  334. "Unknown error" /* Others */
  335. };
  336. return (status_messages[MIN(status,SSH2_FX_MAX)]);
  337. }
  338. static void
  339. send_status(u_int32_t id, u_int32_t status)
  340. {
  341. Buffer msg;
  342. debug3("request %u: sent status %u", id, status);
  343. if (log_level > SYSLOG_LEVEL_VERBOSE ||
  344. (status != SSH2_FX_OK && status != SSH2_FX_EOF))
  345. log("sent status %s", status_to_message(status));
  346. buffer_init(&msg);
  347. buffer_put_char(&msg, SSH2_FXP_STATUS);
  348. buffer_put_int(&msg, id);
  349. buffer_put_int(&msg, status);
  350. if (version >= 3) {
  351. buffer_put_cstring(&msg, status_to_message(status));
  352. buffer_put_cstring(&msg, "");
  353. }
  354. send_msg(&msg);
  355. buffer_free(&msg);
  356. }
  357. static void
  358. send_data_or_handle(char type, u_int32_t id, const char *data, int dlen)
  359. {
  360. Buffer msg;
  361. buffer_init(&msg);
  362. buffer_put_char(&msg, type);
  363. buffer_put_int(&msg, id);
  364. buffer_put_string(&msg, data, dlen);
  365. send_msg(&msg);
  366. buffer_free(&msg);
  367. }
  368. static void
  369. send_data(u_int32_t id, const char *data, int dlen)
  370. {
  371. debug("request %u: sent data len %d", id, dlen);
  372. send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
  373. }
  374. static void
  375. send_handle(u_int32_t id, int handle)
  376. {
  377. char *string;
  378. int hlen;
  379. handle_to_string(handle, &string, &hlen);
  380. debug("request %u: sent handle handle %d", id, handle);
  381. send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
  382. xfree(string);
  383. }
  384. static void
  385. send_names(u_int32_t id, int count, const Stat *stats)
  386. {
  387. Buffer msg;
  388. int i;
  389. buffer_init(&msg);
  390. buffer_put_char(&msg, SSH2_FXP_NAME);
  391. buffer_put_int(&msg, id);
  392. buffer_put_int(&msg, count);
  393. debug("request %u: sent names count %d", id, count);
  394. for (i = 0; i < count; i++) {
  395. buffer_put_cstring(&msg, stats[i].name);
  396. buffer_put_cstring(&msg, stats[i].long_name);
  397. encode_attrib(&msg, &stats[i].attrib);
  398. }
  399. send_msg(&msg);
  400. buffer_free(&msg);
  401. }
  402. static void
  403. send_attrib(u_int32_t id, const Attrib *a)
  404. {
  405. Buffer msg;
  406. debug("request %u: sent attrib have 0x%x", id, a->flags);
  407. buffer_init(&msg);
  408. buffer_put_char(&msg, SSH2_FXP_ATTRS);
  409. buffer_put_int(&msg, id);
  410. encode_attrib(&msg, a);
  411. send_msg(&msg);
  412. buffer_free(&msg);
  413. }
  414. /* parse incoming */
  415. static void
  416. process_init(void)
  417. {
  418. Buffer msg;
  419. version = get_int();
  420. verbose("received client version %d", version);
  421. buffer_init(&msg);
  422. buffer_put_char(&msg, SSH2_FXP_VERSION);
  423. buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
  424. send_msg(&msg);
  425. buffer_free(&msg);
  426. }
  427. static void
  428. process_open(void)
  429. {
  430. u_int32_t id, pflags;
  431. Attrib *a;
  432. char *name;
  433. int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
  434. id = get_int();
  435. name = get_string(NULL);
  436. pflags = get_int(); /* portable flags */
  437. debug3("request %u: open flags %d", id, pflags);
  438. a = get_attrib();
  439. flags = flags_from_portable(pflags);
  440. mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
  441. log("open \"%s\" flags %s mode 0%o",
  442. name, string_from_portable(pflags), mode);
  443. fd = open(name, flags, mode);
  444. if (fd < 0) {
  445. status = errno_to_portable(errno);
  446. } else {
  447. handle = handle_new(HANDLE_FILE, name, fd, NULL);
  448. if (handle < 0) {
  449. close(fd);
  450. } else {
  451. send_handle(id, handle);
  452. status = SSH2_FX_OK;
  453. }
  454. }
  455. if (status != SSH2_FX_OK)
  456. send_status(id, status);
  457. xfree(name);
  458. }
  459. static void
  460. process_close(void)
  461. {
  462. u_int32_t id;
  463. int handle, ret, status = SSH2_FX_FAILURE;
  464. id = get_int();
  465. handle = get_handle();
  466. debug3("request %u: close handle %u", id, handle);
  467. handle_log_close(handle, NULL);
  468. ret = handle_close(handle);
  469. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  470. send_status(id, status);
  471. }
  472. static void
  473. process_read(void)
  474. {
  475. char buf[64*1024];
  476. u_int32_t id, len;
  477. int handle, fd, ret, status = SSH2_FX_FAILURE;
  478. u_int64_t off;
  479. id = get_int();
  480. handle = get_handle();
  481. off = get_int64();
  482. len = get_int();
  483. debug("request %u: read \"%s\" (handle %d) off %llu len %d",
  484. id, handle_to_name(handle), handle, (unsigned long long)off, len);
  485. if (len > sizeof buf) {
  486. len = sizeof buf;
  487. debug2("read change len %d", len);
  488. }
  489. fd = handle_to_fd(handle);
  490. if (fd >= 0) {
  491. if (lseek(fd, off, SEEK_SET) < 0) {
  492. error("process_read: seek failed");
  493. status = errno_to_portable(errno);
  494. } else {
  495. ret = read(fd, buf, len);
  496. if (ret < 0) {
  497. status = errno_to_portable(errno);
  498. } else if (ret == 0) {
  499. status = SSH2_FX_EOF;
  500. } else {
  501. send_data(id, buf, ret);
  502. status = SSH2_FX_OK;
  503. handle_update_read(handle, ret);
  504. }
  505. }
  506. }
  507. if (status != SSH2_FX_OK)
  508. send_status(id, status);
  509. }
  510. static void
  511. process_write(void)
  512. {
  513. u_int32_t id;
  514. u_int64_t off;
  515. u_int len;
  516. int handle, fd, ret, status = SSH2_FX_FAILURE;
  517. char *data;
  518. id = get_int();
  519. handle = get_handle();
  520. off = get_int64();
  521. data = get_string(&len);
  522. debug("request %u: write \"%s\" (handle %d) off %llu len %d",
  523. id, handle_to_name(handle), handle, (unsigned long long)off, len);
  524. fd = handle_to_fd(handle);
  525. if (fd >= 0) {
  526. if (lseek(fd, off, SEEK_SET) < 0) {
  527. status = errno_to_portable(errno);
  528. error("process_write: seek failed");
  529. } else {
  530. /* XXX ATOMICIO ? */
  531. ret = write(fd, data, len);
  532. if (ret < 0) {
  533. error("process_write: write failed");
  534. status = errno_to_portable(errno);
  535. } else if ((size_t)ret == len) {
  536. status = SSH2_FX_OK;
  537. handle_update_write(handle, ret);
  538. } else {
  539. debug2("nothing at all written");
  540. }
  541. }
  542. }
  543. send_status(id, status);
  544. xfree(data);
  545. }
  546. static void
  547. process_do_stat(int do_lstat)
  548. {
  549. Attrib a;
  550. struct stat st;
  551. u_int32_t id;
  552. char *name;
  553. int ret, status = SSH2_FX_FAILURE;
  554. id = get_int();
  555. name = get_string(NULL);
  556. debug3("request %u: %sstat", id, do_lstat ? "l" : "");
  557. verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
  558. ret = do_lstat ? lstat(name, &st) : stat(name, &st);
  559. if (ret < 0) {
  560. status = errno_to_portable(errno);
  561. } else {
  562. stat_to_attrib(&st, &a);
  563. send_attrib(id, &a);
  564. status = SSH2_FX_OK;
  565. }
  566. if (status != SSH2_FX_OK)
  567. send_status(id, status);
  568. xfree(name);
  569. }
  570. static void
  571. process_stat(void)
  572. {
  573. process_do_stat(0);
  574. }
  575. static void
  576. process_lstat(void)
  577. {
  578. process_do_stat(1);
  579. }
  580. static void
  581. process_fstat(void)
  582. {
  583. Attrib a;
  584. struct stat st;
  585. u_int32_t id;
  586. int fd, ret, handle, status = SSH2_FX_FAILURE;
  587. id = get_int();
  588. handle = get_handle();
  589. debug("request %u: fstat \"%s\" (handle %u)",
  590. id, handle_to_name(handle), handle);
  591. fd = handle_to_fd(handle);
  592. if (fd >= 0) {
  593. ret = fstat(fd, &st);
  594. if (ret < 0) {
  595. status = errno_to_portable(errno);
  596. } else {
  597. stat_to_attrib(&st, &a);
  598. send_attrib(id, &a);
  599. status = SSH2_FX_OK;
  600. }
  601. }
  602. if (status != SSH2_FX_OK)
  603. send_status(id, status);
  604. }
  605. static struct timeval *
  606. attrib_to_tv(const Attrib *a)
  607. {
  608. static struct timeval tv[2];
  609. tv[0].tv_sec = a->atime;
  610. tv[0].tv_usec = 0;
  611. tv[1].tv_sec = a->mtime;
  612. tv[1].tv_usec = 0;
  613. return tv;
  614. }
  615. static void
  616. process_setstat(void)
  617. {
  618. Attrib *a;
  619. u_int32_t id;
  620. char *name;
  621. int status = SSH2_FX_OK, ret;
  622. id = get_int();
  623. name = get_string(NULL);
  624. a = get_attrib();
  625. debug("request %u: setstat name \"%s\"", id, name);
  626. if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
  627. log("set \"%s\" size %llu",
  628. name, (unsigned long long)a->size);
  629. ret = truncate(name, a->size);
  630. if (ret == -1)
  631. status = errno_to_portable(errno);
  632. }
  633. if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
  634. log("set \"%s\" mode %04o", name, a->perm);
  635. ret = chmod(name, a->perm & 07777);
  636. if (ret == -1)
  637. status = errno_to_portable(errno);
  638. }
  639. if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
  640. char buf[64];
  641. time_t t = a->mtime;
  642. strftime(buf, sizeof(buf), "%Y" "%m%d-%H:%M:%S",
  643. localtime(&t));
  644. log("set \"%s\" modtime %s", name, buf);
  645. ret = utimes(name, attrib_to_tv(a));
  646. if (ret == -1)
  647. status = errno_to_portable(errno);
  648. }
  649. if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
  650. log("set \"%s\" owner %lu group %lu", name,
  651. (u_long)a->uid, (u_long)a->gid);
  652. ret = chown(name, a->uid, a->gid);
  653. if (ret == -1)
  654. status = errno_to_portable(errno);
  655. }
  656. send_status(id, status);
  657. xfree(name);
  658. }
  659. static void
  660. process_fsetstat(void)
  661. {
  662. Attrib *a;
  663. u_int32_t id;
  664. int handle, fd, ret;
  665. int status = SSH2_FX_OK;
  666. id = get_int();
  667. handle = get_handle();
  668. a = get_attrib();
  669. debug("request %u: fsetstat handle %d", id, handle);
  670. fd = handle_to_fd(handle);
  671. if (fd < 0) {
  672. status = SSH2_FX_FAILURE;
  673. } else {
  674. char *name = handle_to_name(handle);
  675. if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
  676. log("set \"%s\" size %llu",
  677. name, (unsigned long long)a->size);
  678. ret = ftruncate(fd, a->size);
  679. if (ret == -1)
  680. status = errno_to_portable(errno);
  681. }
  682. if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
  683. log("set \"%s\" mode %04o", name, a->perm);
  684. #ifdef HAVE_FCHMOD
  685. ret = fchmod(fd, a->perm & 07777);
  686. #else
  687. ret = chmod(name, a->perm & 07777);
  688. #endif
  689. if (ret == -1)
  690. status = errno_to_portable(errno);
  691. }
  692. if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
  693. char buf[64];
  694. time_t t = a->mtime;
  695. strftime(buf, sizeof(buf), "%Y" "%m%d-%H:%M:%S",
  696. localtime(&t));
  697. log("set \"%s\" modtime %s", name, buf);
  698. #ifdef HAVE_FUTIMES
  699. ret = futimes(fd, attrib_to_tv(a));
  700. #else
  701. ret = utimes(name, attrib_to_tv(a));
  702. #endif
  703. if (ret == -1)
  704. status = errno_to_portable(errno);
  705. }
  706. if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
  707. log("set \"%s\" owner %lu group %lu", name,
  708. (u_long)a->uid, (u_long)a->gid);
  709. #ifdef HAVE_FCHOWN
  710. ret = fchown(fd, a->uid, a->gid);
  711. #else
  712. ret = chown(name, a->uid, a->gid);
  713. #endif
  714. if (ret == -1)
  715. status = errno_to_portable(errno);
  716. }
  717. }
  718. send_status(id, status);
  719. }
  720. static void
  721. process_opendir(void)
  722. {
  723. DIR *dirp = NULL;
  724. char *path;
  725. int handle, status = SSH2_FX_FAILURE;
  726. u_int32_t id;
  727. id = get_int();
  728. path = get_string(NULL);
  729. debug3("request %u: opendir", id);
  730. log("opendir \"%s\"", path);
  731. dirp = opendir(path);
  732. if (dirp == NULL) {
  733. status = errno_to_portable(errno);
  734. } else {
  735. handle = handle_new(HANDLE_DIR, path, 0, dirp);
  736. if (handle < 0) {
  737. closedir(dirp);
  738. } else {
  739. send_handle(id, handle);
  740. status = SSH2_FX_OK;
  741. }
  742. }
  743. if (status != SSH2_FX_OK)
  744. send_status(id, status);
  745. xfree(path);
  746. }
  747. static void
  748. process_readdir(void)
  749. {
  750. DIR *dirp;
  751. struct dirent *dp;
  752. char *path;
  753. int handle;
  754. u_int32_t id;
  755. id = get_int();
  756. handle = get_handle();
  757. debug("request %u: readdir \"%s\" (handle %d)", id,
  758. handle_to_name(handle), handle);
  759. dirp = handle_to_dir(handle);
  760. path = handle_to_name(handle);
  761. if (dirp == NULL || path == NULL) {
  762. send_status(id, SSH2_FX_FAILURE);
  763. } else {
  764. struct stat st;
  765. char pathname[MAXPATHLEN];
  766. Stat *stats;
  767. int nstats = 10, count = 0, i;
  768. stats = xcalloc(nstats, sizeof(Stat));
  769. while ((dp = readdir(dirp)) != NULL) {
  770. if (count >= nstats) {
  771. nstats *= 2;
  772. stats = xrealloc(stats, nstats * sizeof(Stat));
  773. }
  774. /* XXX OVERFLOW ? */
  775. snprintf(pathname, sizeof pathname, "%s%s%s", path,
  776. strcmp(path, "/") ? "/" : "", dp->d_name);
  777. if (lstat(pathname, &st) < 0)
  778. continue;
  779. stat_to_attrib(&st, &(stats[count].attrib));
  780. stats[count].name = xstrdup(dp->d_name);
  781. stats[count].long_name = ls_file(dp->d_name, &st, 0);
  782. count++;
  783. /* send up to 100 entries in one message */
  784. /* XXX check packet size instead */
  785. if (count == 100)
  786. break;
  787. }
  788. if (count > 0) {
  789. send_names(id, count, stats);
  790. for (i = 0; i < count; i++) {
  791. xfree(stats[i].name);
  792. xfree(stats[i].long_name);
  793. }
  794. } else {
  795. send_status(id, SSH2_FX_EOF);
  796. }
  797. xfree(stats);
  798. }
  799. }
  800. static void
  801. process_remove(void)
  802. {
  803. char *name;
  804. u_int32_t id;
  805. int status = SSH2_FX_FAILURE;
  806. int ret;
  807. id = get_int();
  808. name = get_string(NULL);
  809. debug3("request %u: remove", id);
  810. log("remove name \"%s\"", name);
  811. ret = unlink(name);
  812. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  813. send_status(id, status);
  814. xfree(name);
  815. }
  816. static void
  817. process_mkdir(void)
  818. {
  819. Attrib *a;
  820. u_int32_t id;
  821. char *name;
  822. int ret, mode, status = SSH2_FX_FAILURE;
  823. id = get_int();
  824. name = get_string(NULL);
  825. a = get_attrib();
  826. mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
  827. a->perm & 0777 : 0777;
  828. debug3("request %u: mkdir", id);
  829. log("mkdir name \"%s\" mode 0%o", name, mode);
  830. ret = mkdir(name, mode);
  831. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  832. send_status(id, status);
  833. xfree(name);
  834. }
  835. static void
  836. process_rmdir(void)
  837. {
  838. u_int32_t id;
  839. char *name;
  840. int ret, status;
  841. id = get_int();
  842. name = get_string(NULL);
  843. debug3("request %u: rmdir", id);
  844. log("rmdir name \"%s\"", name);
  845. ret = rmdir(name);
  846. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  847. send_status(id, status);
  848. xfree(name);
  849. }
  850. static void
  851. process_realpath(void)
  852. {
  853. char resolvedname[MAXPATHLEN];
  854. u_int32_t id;
  855. char *path;
  856. id = get_int();
  857. path = get_string(NULL);
  858. if (path[0] == '\0') {
  859. xfree(path);
  860. path = xstrdup(".");
  861. }
  862. debug3("request %u: realpath", id);
  863. verbose("realpath \"%s\"", path);
  864. if (realpath(path, resolvedname) == NULL) {
  865. send_status(id, errno_to_portable(errno));
  866. } else {
  867. Stat s;
  868. attrib_clear(&s.attrib);
  869. s.name = s.long_name = resolvedname;
  870. send_names(id, 1, &s);
  871. }
  872. xfree(path);
  873. }
  874. static void
  875. process_rename(void)
  876. {
  877. u_int32_t id;
  878. char *oldpath, *newpath;
  879. int status;
  880. struct stat sb;
  881. id = get_int();
  882. oldpath = get_string(NULL);
  883. newpath = get_string(NULL);
  884. debug3("request %u: rename", id);
  885. log("rename old \"%s\" new \"%s\"", oldpath, newpath);
  886. status = SSH2_FX_FAILURE;
  887. if (lstat(oldpath, &sb) == -1)
  888. status = errno_to_portable(errno);
  889. else if (S_ISREG(sb.st_mode)) {
  890. /* Race-free rename of regular files */
  891. if (link(oldpath, newpath) == -1) {
  892. if (errno == EOPNOTSUPP
  893. #ifdef LINK_OPNOTSUPP_ERRNO
  894. || errno == LINK_OPNOTSUPP_ERRNO
  895. #endif
  896. ) {
  897. struct stat st;
  898. /*
  899. * fs doesn't support links, so fall back to
  900. * stat+rename. This is racy.
  901. */
  902. if (stat(newpath, &st) == -1) {
  903. if (rename(oldpath, newpath) == -1)
  904. status =
  905. errno_to_portable(errno);
  906. else
  907. status = SSH2_FX_OK;
  908. }
  909. } else {
  910. status = errno_to_portable(errno);
  911. }
  912. } else if (unlink(oldpath) == -1) {
  913. status = errno_to_portable(errno);
  914. /* clean spare link */
  915. unlink(newpath);
  916. } else
  917. status = SSH2_FX_OK;
  918. } else if (stat(newpath, &sb) == -1) {
  919. if (rename(oldpath, newpath) == -1)
  920. status = errno_to_portable(errno);
  921. else
  922. status = SSH2_FX_OK;
  923. }
  924. send_status(id, status);
  925. xfree(oldpath);
  926. xfree(newpath);
  927. }
  928. static void
  929. process_readlink(void)
  930. {
  931. u_int32_t id;
  932. int len;
  933. char buf[MAXPATHLEN];
  934. char *path;
  935. id = get_int();
  936. path = get_string(NULL);
  937. debug3("request %u: readlink", id);
  938. verbose("readlink \"%s\"", path);
  939. if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
  940. send_status(id, errno_to_portable(errno));
  941. else {
  942. Stat s;
  943. buf[len] = '\0';
  944. attrib_clear(&s.attrib);
  945. s.name = s.long_name = buf;
  946. send_names(id, 1, &s);
  947. }
  948. xfree(path);
  949. }
  950. static void
  951. process_symlink(void)
  952. {
  953. u_int32_t id;
  954. char *oldpath, *newpath;
  955. int ret, status;
  956. id = get_int();
  957. oldpath = get_string(NULL);
  958. newpath = get_string(NULL);
  959. debug3("request %u: symlink", id);
  960. log("symlink old \"%s\" new \"%s\"", oldpath, newpath);
  961. /* this will fail if 'newpath' exists */
  962. ret = symlink(oldpath, newpath);
  963. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  964. send_status(id, status);
  965. xfree(oldpath);
  966. xfree(newpath);
  967. }
  968. static void
  969. process_extended(void)
  970. {
  971. u_int32_t id;
  972. char *request;
  973. id = get_int();
  974. request = get_string(NULL);
  975. send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
  976. xfree(request);
  977. }
  978. /* stolen from ssh-agent */
  979. static void
  980. process(void)
  981. {
  982. u_int msg_len;
  983. u_int buf_len;
  984. u_int consumed;
  985. u_int type;
  986. u_char *cp;
  987. buf_len = buffer_len(&iqueue);
  988. if (buf_len < 5)
  989. return; /* Incomplete message. */
  990. cp = buffer_ptr(&iqueue);
  991. msg_len = get_u32(cp);
  992. if (msg_len > SFTP_MAX_MSG_LENGTH) {
  993. error("bad message from %s local user %s",
  994. client_addr, pw->pw_name);
  995. cleanup_exit(11);
  996. }
  997. if (buf_len < msg_len + 4)
  998. return;
  999. buffer_consume(&iqueue, 4);
  1000. buf_len -= 4;
  1001. type = buffer_get_char(&iqueue);
  1002. switch (type) {
  1003. case SSH2_FXP_INIT:
  1004. process_init();
  1005. break;
  1006. case SSH2_FXP_OPEN:
  1007. process_open();
  1008. break;
  1009. case SSH2_FXP_CLOSE:
  1010. process_close();
  1011. break;
  1012. case SSH2_FXP_READ:
  1013. process_read();
  1014. break;
  1015. case SSH2_FXP_WRITE:
  1016. process_write();
  1017. break;
  1018. case SSH2_FXP_LSTAT:
  1019. process_lstat();
  1020. break;
  1021. case SSH2_FXP_FSTAT:
  1022. process_fstat();
  1023. break;
  1024. case SSH2_FXP_SETSTAT:
  1025. process_setstat();
  1026. break;
  1027. case SSH2_FXP_FSETSTAT:
  1028. process_fsetstat();
  1029. break;
  1030. case SSH2_FXP_OPENDIR:
  1031. process_opendir();
  1032. break;
  1033. case SSH2_FXP_READDIR:
  1034. process_readdir();
  1035. break;
  1036. case SSH2_FXP_REMOVE:
  1037. process_remove();
  1038. break;
  1039. case SSH2_FXP_MKDIR:
  1040. process_mkdir();
  1041. break;
  1042. case SSH2_FXP_RMDIR:
  1043. process_rmdir();
  1044. break;
  1045. case SSH2_FXP_REALPATH:
  1046. process_realpath();
  1047. break;
  1048. case SSH2_FXP_STAT:
  1049. process_stat();
  1050. break;
  1051. case SSH2_FXP_RENAME:
  1052. process_rename();
  1053. break;
  1054. case SSH2_FXP_READLINK:
  1055. process_readlink();
  1056. break;
  1057. case SSH2_FXP_SYMLINK:
  1058. process_symlink();
  1059. break;
  1060. case SSH2_FXP_EXTENDED:
  1061. process_extended();
  1062. break;
  1063. default:
  1064. error("Unknown message %d", type);
  1065. break;
  1066. }
  1067. /* discard the remaining bytes from the current packet */
  1068. if (buf_len < buffer_len(&iqueue))
  1069. fatal("iqueue grew unexpectedly");
  1070. consumed = buf_len - buffer_len(&iqueue);
  1071. if (msg_len < consumed)
  1072. fatal("msg_len %d < consumed %d", msg_len, consumed);
  1073. if (msg_len > consumed)
  1074. buffer_consume(&iqueue, msg_len - consumed);
  1075. }
  1076. /*
  1077. * Cleanup handler that logs active handles upon normal exit. Not static since
  1078. * sftp-server-main.c file needs that as well.
  1079. */
  1080. void
  1081. cleanup_exit(int i)
  1082. {
  1083. if (pw != NULL && client_addr != NULL) {
  1084. handle_log_exit();
  1085. log("session closed for local user %s from [%s]",
  1086. pw->pw_name, client_addr);
  1087. }
  1088. _exit(i);
  1089. }
  1090. static void
  1091. usage(void)
  1092. {
  1093. fprintf(stderr,
  1094. "Usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname);
  1095. exit(1);
  1096. }
  1097. int
  1098. sftp_server_main(int argc, char **argv, struct passwd *user_pw)
  1099. {
  1100. fd_set *rset, *wset;
  1101. int in, out, max, ch, skipargs = 0, log_stderr = 0;
  1102. ssize_t len, olen, set_size;
  1103. SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
  1104. char *cp, buf[4*4096];
  1105. extern char *optarg;
  1106. __progname = get_progname(argv[0]);
  1107. (void) g11n_setlocale(LC_ALL, "");
  1108. log_init(__progname, log_level, log_facility, log_stderr);
  1109. while (!skipargs && (ch = getopt(argc, argv, "C:f:l:che")) != -1) {
  1110. switch (ch) {
  1111. case 'c':
  1112. /*
  1113. * Ignore all arguments if we are invoked as a
  1114. * shell using "sftp-server -c command"
  1115. */
  1116. skipargs = 1;
  1117. break;
  1118. case 'e':
  1119. log_stderr = 1;
  1120. break;
  1121. case 'l':
  1122. log_level = log_level_number(optarg);
  1123. if (log_level == SYSLOG_LEVEL_NOT_SET)
  1124. error("Invalid log level \"%s\"", optarg);
  1125. break;
  1126. case 'f':
  1127. log_facility = log_facility_number(optarg);
  1128. if (log_facility == SYSLOG_FACILITY_NOT_SET)
  1129. error("Invalid log facility \"%s\"", optarg);
  1130. break;
  1131. case 'h':
  1132. default:
  1133. usage();
  1134. }
  1135. }
  1136. log_init(__progname, log_level, log_facility, log_stderr);
  1137. if ((cp = getenv("SSH_CONNECTION")) != NULL) {
  1138. client_addr = xstrdup(cp);
  1139. if ((cp = strchr(client_addr, ' ')) == NULL)
  1140. fatal("Malformed SSH_CONNECTION variable: \"%s\"",
  1141. getenv("SSH_CONNECTION"));
  1142. *cp = '\0';
  1143. } else
  1144. client_addr = xstrdup("UNKNOWN");
  1145. pw = pwcopy(user_pw);
  1146. log("session opened for local user %s from [%s]",
  1147. pw->pw_name, client_addr);
  1148. handle_init();
  1149. in = dup(STDIN_FILENO);
  1150. out = dup(STDOUT_FILENO);
  1151. #ifdef HAVE_CYGWIN
  1152. setmode(in, O_BINARY);
  1153. setmode(out, O_BINARY);
  1154. #endif
  1155. max = 0;
  1156. if (in > max)
  1157. max = in;
  1158. if (out > max)
  1159. max = out;
  1160. buffer_init(&iqueue);
  1161. buffer_init(&oqueue);
  1162. set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
  1163. rset = (fd_set *)xmalloc(set_size);
  1164. wset = (fd_set *)xmalloc(set_size);
  1165. for (;;) {
  1166. memset(rset, 0, set_size);
  1167. memset(wset, 0, set_size);
  1168. /*
  1169. * Ensure that we can read a full buffer and handle
  1170. * the worst-case length packet it can generate,
  1171. * otherwise apply backpressure by stopping reads.
  1172. */
  1173. if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
  1174. buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
  1175. FD_SET(in, rset);
  1176. olen = buffer_len(&oqueue);
  1177. if (olen > 0)
  1178. FD_SET(out, wset);
  1179. if (select(max+1, rset, wset, NULL, NULL) < 0) {
  1180. if (errno == EINTR)
  1181. continue;
  1182. error("select: %s", strerror(errno));
  1183. cleanup_exit(2);
  1184. }
  1185. /* copy stdin to iqueue */
  1186. if (FD_ISSET(in, rset)) {
  1187. len = read(in, buf, sizeof buf);
  1188. if (len == 0) {
  1189. debug("read eof");
  1190. cleanup_exit(0);
  1191. } else if (len < 0) {
  1192. error("read: %s", strerror(errno));
  1193. cleanup_exit(1);
  1194. } else {
  1195. buffer_append(&iqueue, buf, len);
  1196. }
  1197. }
  1198. /* send oqueue to stdout */
  1199. if (FD_ISSET(out, wset)) {
  1200. len = write(out, buffer_ptr(&oqueue), olen);
  1201. if (len < 0) {
  1202. error("write: %s", strerror(errno));
  1203. cleanup_exit(1);
  1204. } else {
  1205. buffer_consume(&oqueue, len);
  1206. }
  1207. }
  1208. /*
  1209. * Process requests from client if we can fit the results
  1210. * into the output buffer, otherwise stop processing input
  1211. * and let the output queue drain.
  1212. */
  1213. if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
  1214. process();
  1215. }
  1216. /* NOTREACHED */
  1217. return (0);
  1218. }