PageRenderTime 59ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/backup/sftp.in.sv.gnu.org/var/www/arch/patches/sftp-server.c

#
C | 1170 lines | 976 code | 154 blank | 40 comment | 156 complexity | 713a97738b0fb3f05c19a0d7f8f424d9 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  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. #include "includes.h"
  17. RCSID("$OpenBSD: sftp-server.c,v 1.45 2004/02/19 21:15:04 markus Exp $");
  18. /*
  19. * Patched for GNU Arch support 2005.
  20. * Patch released under public domain.
  21. * 2005 - Michael J. Flickinger
  22. */
  23. #include "buffer.h"
  24. #include "bufaux.h"
  25. #include "getput.h"
  26. #include "log.h"
  27. #include "xmalloc.h"
  28. #include <sys/types.h>
  29. #include <sys/file.h>
  30. #include <sys/stat.h>
  31. #include <syslog.h>
  32. #include <unistd.h>
  33. #include <time.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <regex.h>
  37. #include <fcntl.h>
  38. #include <pwd.h>
  39. #include "sftp.h"
  40. #include "sftp-common.h"
  41. #define SEAL_ARCHIVES "/utils/seal-archives"
  42. #define ARCHIVE_PATH "^/archives/|^/var/lib/arch/" // path, (regex)
  43. #define COMMIT_NOTICE "/utils/mail-on-commit.pl" // comment out if not desired
  44. /* helper */
  45. #define get_int64() buffer_get_int64(&iqueue);
  46. #define get_int() buffer_get_int(&iqueue);
  47. #define get_string(lenp) buffer_get_string(&iqueue, lenp);
  48. #define TRACE debug
  49. #ifdef HAVE___PROGNAME
  50. extern char *__progname;
  51. #else
  52. char *__progname;
  53. #endif
  54. /* input and output queue */
  55. Buffer iqueue;
  56. Buffer oqueue;
  57. /* Version of client */
  58. int version;
  59. /* portable attributes, etc. */
  60. typedef struct Stat Stat;
  61. struct Stat {
  62. char *name;
  63. char *long_name;
  64. Attrib attrib;
  65. };
  66. struct passwd *password_data;
  67. static void
  68. sec_log (char *message, ...)
  69. {
  70. va_list args;
  71. char msgbuf[2048];
  72. char *connection = getenv("SSH_CLIENT");
  73. va_start(args, message);
  74. vsnprintf(msgbuf, sizeof(msgbuf), message, args);
  75. setlogmask (LOG_UPTO (LOG_NOTICE));
  76. openlog ("sftp-server", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
  77. syslog(LOG_NOTICE, "user: %s -- uid: %i -- from: %s -- %s\n", password_data->pw_name, getuid(), connection, msgbuf);
  78. closelog ();
  79. va_end(args);
  80. }
  81. static int
  82. regex_match (char *pat, const char* string)
  83. {
  84. int result;
  85. regex_t re;
  86. if (regcomp(&re, pat, REG_EXTENDED|REG_NOSUB) != 0)
  87. return(-1);
  88. result = regexec(&re, string, (size_t) 0, NULL, 0);
  89. regfree(&re);
  90. if (result != 0)
  91. return(0);
  92. return(1);
  93. }
  94. static int
  95. errno_to_portable(int unixerrno)
  96. {
  97. int ret = 0;
  98. switch (unixerrno) {
  99. case 0:
  100. ret = SSH2_FX_OK;
  101. break;
  102. case ENOENT:
  103. case ENOTDIR:
  104. case EBADF:
  105. case ELOOP:
  106. ret = SSH2_FX_NO_SUCH_FILE;
  107. break;
  108. case EPERM:
  109. case EACCES:
  110. case EFAULT:
  111. ret = SSH2_FX_PERMISSION_DENIED;
  112. break;
  113. case ENAMETOOLONG:
  114. case EINVAL:
  115. ret = SSH2_FX_BAD_MESSAGE;
  116. break;
  117. default:
  118. ret = SSH2_FX_FAILURE;
  119. break;
  120. }
  121. return ret;
  122. }
  123. static int
  124. flags_from_portable(int pflags)
  125. {
  126. int flags = 0;
  127. if ((pflags & SSH2_FXF_READ) &&
  128. (pflags & SSH2_FXF_WRITE)) {
  129. flags = O_RDWR;
  130. } else if (pflags & SSH2_FXF_READ) {
  131. flags = O_RDONLY;
  132. } else if (pflags & SSH2_FXF_WRITE) {
  133. flags = O_WRONLY;
  134. }
  135. if (pflags & SSH2_FXF_CREAT)
  136. flags |= O_CREAT;
  137. if (pflags & SSH2_FXF_TRUNC)
  138. flags |= O_TRUNC;
  139. if (pflags & SSH2_FXF_EXCL)
  140. flags |= O_EXCL;
  141. return flags;
  142. }
  143. static Attrib *
  144. get_attrib(void)
  145. {
  146. return decode_attrib(&iqueue);
  147. }
  148. /* handle handles */
  149. typedef struct Handle Handle;
  150. struct Handle {
  151. int use;
  152. DIR *dirp;
  153. int fd;
  154. char *name;
  155. };
  156. enum {
  157. HANDLE_UNUSED,
  158. HANDLE_DIR,
  159. HANDLE_FILE
  160. };
  161. Handle handles[100];
  162. static void
  163. handle_init(void)
  164. {
  165. int i;
  166. for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
  167. handles[i].use = HANDLE_UNUSED;
  168. sec_log("login to arch sftp subsystem");
  169. }
  170. static int
  171. handle_new(int use, const char *name, int fd, DIR *dirp)
  172. {
  173. int i;
  174. for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) {
  175. if (handles[i].use == HANDLE_UNUSED) {
  176. handles[i].use = use;
  177. handles[i].dirp = dirp;
  178. handles[i].fd = fd;
  179. handles[i].name = xstrdup(name);
  180. return i;
  181. }
  182. }
  183. return -1;
  184. }
  185. static int
  186. handle_is_ok(int i, int type)
  187. {
  188. return i >= 0 && i < sizeof(handles)/sizeof(Handle) &&
  189. handles[i].use == type;
  190. }
  191. static int
  192. handle_to_string(int handle, char **stringp, int *hlenp)
  193. {
  194. if (stringp == NULL || hlenp == NULL)
  195. return -1;
  196. *stringp = xmalloc(sizeof(int32_t));
  197. PUT_32BIT(*stringp, handle);
  198. *hlenp = sizeof(int32_t);
  199. return 0;
  200. }
  201. static int
  202. handle_from_string(const char *handle, u_int hlen)
  203. {
  204. int val;
  205. if (hlen != sizeof(int32_t))
  206. return -1;
  207. val = GET_32BIT(handle);
  208. if (handle_is_ok(val, HANDLE_FILE) ||
  209. handle_is_ok(val, HANDLE_DIR))
  210. return val;
  211. return -1;
  212. }
  213. static char *
  214. handle_to_name(int handle)
  215. {
  216. if (handle_is_ok(handle, HANDLE_DIR)||
  217. handle_is_ok(handle, HANDLE_FILE))
  218. return handles[handle].name;
  219. return NULL;
  220. }
  221. static DIR *
  222. handle_to_dir(int handle)
  223. {
  224. if (handle_is_ok(handle, HANDLE_DIR))
  225. return handles[handle].dirp;
  226. return NULL;
  227. }
  228. static int
  229. handle_to_fd(int handle)
  230. {
  231. if (handle_is_ok(handle, HANDLE_FILE))
  232. return handles[handle].fd;
  233. return -1;
  234. }
  235. static int
  236. handle_close(int handle)
  237. {
  238. int ret = -1;
  239. if (handle_is_ok(handle, HANDLE_FILE)) {
  240. ret = close(handles[handle].fd);
  241. handles[handle].use = HANDLE_UNUSED;
  242. xfree(handles[handle].name);
  243. } else if (handle_is_ok(handle, HANDLE_DIR)) {
  244. ret = closedir(handles[handle].dirp);
  245. handles[handle].use = HANDLE_UNUSED;
  246. xfree(handles[handle].name);
  247. } else {
  248. errno = ENOENT;
  249. }
  250. return ret;
  251. }
  252. static int
  253. get_handle(void)
  254. {
  255. char *handle;
  256. int val = -1;
  257. u_int hlen;
  258. handle = get_string(&hlen);
  259. if (hlen < 256)
  260. val = handle_from_string(handle, hlen);
  261. xfree(handle);
  262. return val;
  263. }
  264. /* send replies */
  265. static void
  266. send_msg(Buffer *m)
  267. {
  268. int mlen = buffer_len(m);
  269. buffer_put_int(&oqueue, mlen);
  270. buffer_append(&oqueue, buffer_ptr(m), mlen);
  271. buffer_consume(m, mlen);
  272. }
  273. static void
  274. send_status(u_int32_t id, u_int32_t error)
  275. {
  276. Buffer msg;
  277. const char *status_messages[] = {
  278. "Success", /* SSH_FX_OK */
  279. "End of file", /* SSH_FX_EOF */
  280. "No such file", /* SSH_FX_NO_SUCH_FILE */
  281. "Permission denied", /* SSH_FX_PERMISSION_DENIED */
  282. "Failure", /* SSH_FX_FAILURE */
  283. "Bad message", /* SSH_FX_BAD_MESSAGE */
  284. "No connection", /* SSH_FX_NO_CONNECTION */
  285. "Connection lost", /* SSH_FX_CONNECTION_LOST */
  286. "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
  287. "Unknown error" /* Others */
  288. };
  289. TRACE("sent status id %u error %u", id, error);
  290. buffer_init(&msg);
  291. buffer_put_char(&msg, SSH2_FXP_STATUS);
  292. buffer_put_int(&msg, id);
  293. buffer_put_int(&msg, error);
  294. if (version >= 3) {
  295. buffer_put_cstring(&msg,
  296. status_messages[MIN(error,SSH2_FX_MAX)]);
  297. buffer_put_cstring(&msg, "");
  298. }
  299. send_msg(&msg);
  300. buffer_free(&msg);
  301. }
  302. static void
  303. send_data_or_handle(char type, u_int32_t id, const char *data, int dlen)
  304. {
  305. Buffer msg;
  306. buffer_init(&msg);
  307. buffer_put_char(&msg, type);
  308. buffer_put_int(&msg, id);
  309. buffer_put_string(&msg, data, dlen);
  310. send_msg(&msg);
  311. buffer_free(&msg);
  312. }
  313. static void
  314. send_data(u_int32_t id, const char *data, int dlen)
  315. {
  316. TRACE("sent data id %u len %d", id, dlen);
  317. send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
  318. }
  319. static void
  320. send_handle(u_int32_t id, int handle)
  321. {
  322. char *string;
  323. int hlen;
  324. handle_to_string(handle, &string, &hlen);
  325. TRACE("sent handle id %u handle %d", id, handle);
  326. send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
  327. xfree(string);
  328. }
  329. static void
  330. send_names(u_int32_t id, int count, const Stat *stats)
  331. {
  332. Buffer msg;
  333. int i;
  334. buffer_init(&msg);
  335. buffer_put_char(&msg, SSH2_FXP_NAME);
  336. buffer_put_int(&msg, id);
  337. buffer_put_int(&msg, count);
  338. TRACE("sent names id %u count %d", id, count);
  339. for (i = 0; i < count; i++) {
  340. buffer_put_cstring(&msg, stats[i].name);
  341. buffer_put_cstring(&msg, stats[i].long_name);
  342. encode_attrib(&msg, &stats[i].attrib);
  343. }
  344. send_msg(&msg);
  345. buffer_free(&msg);
  346. }
  347. static void
  348. send_attrib(u_int32_t id, const Attrib *a)
  349. {
  350. Buffer msg;
  351. TRACE("sent attrib id %u have 0x%x", id, a->flags);
  352. buffer_init(&msg);
  353. buffer_put_char(&msg, SSH2_FXP_ATTRS);
  354. buffer_put_int(&msg, id);
  355. encode_attrib(&msg, a);
  356. send_msg(&msg);
  357. buffer_free(&msg);
  358. }
  359. /* parse incoming */
  360. static void
  361. process_init(void)
  362. {
  363. Buffer msg;
  364. version = get_int();
  365. TRACE("client version %d", version);
  366. buffer_init(&msg);
  367. buffer_put_char(&msg, SSH2_FXP_VERSION);
  368. buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
  369. send_msg(&msg);
  370. buffer_free(&msg);
  371. }
  372. static void
  373. process_open(void)
  374. {
  375. u_int32_t id, pflags;
  376. Attrib *a;
  377. char *name;
  378. int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
  379. id = get_int();
  380. name = get_string(NULL);
  381. pflags = get_int(); /* portable flags */
  382. a = get_attrib();
  383. flags = flags_from_portable(pflags);
  384. mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
  385. TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode);
  386. if (regex_match(ARCHIVE_PATH, name))
  387. {
  388. if (pflags == 1)
  389. sec_log("\"%s\" opened for reading.", name);
  390. else
  391. sec_log("\"%s\" opened for writing.", name);
  392. fd = open(name, flags, mode);
  393. if (fd < 0) {
  394. status = errno_to_portable(errno);
  395. } else {
  396. handle = handle_new(HANDLE_FILE, name, fd, NULL);
  397. if (handle < 0) {
  398. close(fd);
  399. } else {
  400. send_handle(id, handle);
  401. status = SSH2_FX_OK;
  402. }
  403. }
  404. if (status != SSH2_FX_OK)
  405. send_status(id, status);
  406. }
  407. else
  408. send_status(id, 3);
  409. xfree(name);
  410. }
  411. static void
  412. process_close(void)
  413. {
  414. u_int32_t id;
  415. int handle, ret, status = SSH2_FX_FAILURE;
  416. id = get_int();
  417. handle = get_handle();
  418. TRACE("close id %u handle %d", id, handle);
  419. ret = handle_close(handle);
  420. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  421. send_status(id, status);
  422. }
  423. static void
  424. process_read(void)
  425. {
  426. char buf[64*1024];
  427. u_int32_t id, len;
  428. int handle, fd, ret, status = SSH2_FX_FAILURE;
  429. u_int64_t off;
  430. id = get_int();
  431. handle = get_handle();
  432. off = get_int64();
  433. len = get_int();
  434. TRACE("read id %u handle %d off %llu len %d", id, handle,
  435. (u_int64_t)off, len);
  436. if (len > sizeof buf) {
  437. len = sizeof buf;
  438. logit("read change len %d", len);
  439. }
  440. fd = handle_to_fd(handle);
  441. if (fd >= 0) {
  442. if (lseek(fd, off, SEEK_SET) < 0) {
  443. error("process_read: seek failed");
  444. status = errno_to_portable(errno);
  445. } else {
  446. ret = read(fd, buf, len);
  447. if (ret < 0) {
  448. status = errno_to_portable(errno);
  449. } else if (ret == 0) {
  450. status = SSH2_FX_EOF;
  451. } else {
  452. send_data(id, buf, ret);
  453. status = SSH2_FX_OK;
  454. }
  455. }
  456. }
  457. if (status != SSH2_FX_OK)
  458. send_status(id, status);
  459. }
  460. static void
  461. process_write(void)
  462. {
  463. u_int32_t id;
  464. u_int64_t off;
  465. u_int len;
  466. int handle, fd, ret, status = SSH2_FX_FAILURE;
  467. char *data;
  468. char *name;
  469. id = get_int();
  470. handle = get_handle();
  471. off = get_int64();
  472. data = get_string(&len);
  473. TRACE("write id %u handle %d off %llu len %d", id, handle,
  474. (u_int64_t)off, len);
  475. fd = handle_to_fd(handle);
  476. name = handle_to_name(handle);
  477. if (fd >= 0) {
  478. if (lseek(fd, off, SEEK_SET) < 0) {
  479. status = errno_to_portable(errno);
  480. error("process_write: seek failed");
  481. } else {
  482. /* XXX ATOMICIO ? */
  483. ret = write(fd, data, len);
  484. if (ret == -1) {
  485. error("process_write: write failed");
  486. status = errno_to_portable(errno);
  487. } else if (ret == len) {
  488. status = SSH2_FX_OK;
  489. } else {
  490. logit("nothing at all written");
  491. }
  492. }
  493. }
  494. chmod(name, 0664);
  495. sec_log("sealing: \"%s\"", name);
  496. if (fork()==0)
  497. {
  498. execl(SEAL_ARCHIVES, SEAL_ARCHIVES, name, (char*)0);
  499. exit(1);
  500. }
  501. send_status(id, status);
  502. xfree(data);
  503. }
  504. static void
  505. process_do_stat(int do_lstat)
  506. {
  507. Attrib a;
  508. struct stat st;
  509. u_int32_t id;
  510. char *name;
  511. int ret, status = SSH2_FX_FAILURE;
  512. id = get_int();
  513. name = get_string(NULL);
  514. TRACE("%sstat id %u name %s", do_lstat ? "l" : "", id, name);
  515. ret = do_lstat ? lstat(name, &st) : stat(name, &st);
  516. if (ret < 0) {
  517. status = errno_to_portable(errno);
  518. } else {
  519. stat_to_attrib(&st, &a);
  520. send_attrib(id, &a);
  521. status = SSH2_FX_OK;
  522. }
  523. if (status != SSH2_FX_OK)
  524. send_status(id, status);
  525. xfree(name);
  526. }
  527. static void
  528. process_stat(void)
  529. {
  530. process_do_stat(0);
  531. }
  532. static void
  533. process_lstat(void)
  534. {
  535. process_do_stat(1);
  536. }
  537. static void
  538. process_fstat(void)
  539. {
  540. Attrib a;
  541. struct stat st;
  542. u_int32_t id;
  543. int fd, ret, handle, status = SSH2_FX_FAILURE;
  544. id = get_int();
  545. handle = get_handle();
  546. TRACE("fstat id %u handle %d", id, handle);
  547. fd = handle_to_fd(handle);
  548. if (fd >= 0) {
  549. ret = fstat(fd, &st);
  550. if (ret < 0) {
  551. status = errno_to_portable(errno);
  552. } else {
  553. stat_to_attrib(&st, &a);
  554. send_attrib(id, &a);
  555. status = SSH2_FX_OK;
  556. }
  557. }
  558. if (status != SSH2_FX_OK)
  559. send_status(id, status);
  560. }
  561. static void
  562. process_setstat(void)
  563. {
  564. u_int32_t id;
  565. id = get_int();
  566. send_status(id, 0);
  567. }
  568. static void
  569. process_fsetstat(void)
  570. {
  571. u_int32_t id;
  572. id = get_int();
  573. send_status(id, 0);
  574. }
  575. static void
  576. process_opendir(void)
  577. {
  578. DIR *dirp = NULL;
  579. char *path;
  580. int handle, status = SSH2_FX_FAILURE;
  581. u_int32_t id;
  582. id = get_int();
  583. path = get_string(NULL);
  584. TRACE("opendir id %u path %s", id, path);
  585. dirp = opendir(path);
  586. if (dirp == NULL) {
  587. status = errno_to_portable(errno);
  588. } else {
  589. handle = handle_new(HANDLE_DIR, path, 0, dirp);
  590. if (handle < 0) {
  591. closedir(dirp);
  592. } else {
  593. send_handle(id, handle);
  594. status = SSH2_FX_OK;
  595. }
  596. }
  597. if (status != SSH2_FX_OK)
  598. send_status(id, status);
  599. xfree(path);
  600. }
  601. static void
  602. process_readdir(void)
  603. {
  604. DIR *dirp;
  605. struct dirent *dp;
  606. char *path;
  607. int handle;
  608. u_int32_t id;
  609. id = get_int();
  610. handle = get_handle();
  611. TRACE("readdir id %u handle %d", id, handle);
  612. dirp = handle_to_dir(handle);
  613. path = handle_to_name(handle);
  614. if (dirp == NULL || path == NULL) {
  615. send_status(id, SSH2_FX_FAILURE);
  616. } else {
  617. struct stat st;
  618. char pathname[1024];
  619. Stat *stats;
  620. int nstats = 10, count = 0, i;
  621. stats = xmalloc(nstats * sizeof(Stat));
  622. while ((dp = readdir(dirp)) != NULL) {
  623. if (count >= nstats) {
  624. nstats *= 2;
  625. stats = xrealloc(stats, nstats * sizeof(Stat));
  626. }
  627. /* XXX OVERFLOW ? */
  628. snprintf(pathname, sizeof pathname, "%s%s%s", path,
  629. strcmp(path, "/") ? "/" : "", dp->d_name);
  630. if (lstat(pathname, &st) < 0)
  631. continue;
  632. stat_to_attrib(&st, &(stats[count].attrib));
  633. stats[count].name = xstrdup(dp->d_name);
  634. stats[count].long_name = ls_file(dp->d_name, &st, 0);
  635. count++;
  636. /* send up to 100 entries in one message */
  637. /* XXX check packet size instead */
  638. if (count == 100)
  639. break;
  640. }
  641. if (count > 0) {
  642. send_names(id, count, stats);
  643. for (i = 0; i < count; i++) {
  644. xfree(stats[i].name);
  645. xfree(stats[i].long_name);
  646. }
  647. } else {
  648. send_status(id, SSH2_FX_EOF);
  649. }
  650. xfree(stats);
  651. }
  652. }
  653. static void
  654. process_remove(void)
  655. {
  656. char *name;
  657. u_int32_t id;
  658. int status = SSH2_FX_FAILURE;
  659. int ret;
  660. id = get_int();
  661. name = get_string(NULL);
  662. TRACE("remove id %u name %s", id, name);
  663. if (regex_match(ARCHIVE_PATH, name))
  664. {
  665. ret = unlink(name);
  666. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  667. if (ret != -1)
  668. sec_log("removed \"%s\"", name);
  669. send_status(id, status);
  670. }
  671. else
  672. send_status(id, 3);
  673. xfree(name);
  674. }
  675. static void
  676. process_mkdir(void)
  677. {
  678. Attrib *a;
  679. u_int32_t id;
  680. char *name;
  681. int ret, mode, status = SSH2_FX_FAILURE;
  682. id = get_int();
  683. name = get_string(NULL);
  684. a = get_attrib();
  685. mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
  686. a->perm & 0777 : 0777;
  687. TRACE("mkdir id %u name %s mode 0%o", id, name, mode);
  688. if (regex_match(ARCHIVE_PATH, name))
  689. {
  690. sec_log("\"%s\" directory created.", name);
  691. ret = mkdir(name, 02775);
  692. sec_log("creating directory: %s\n", name);
  693. if (ret != -1)
  694. ret = chmod(name, 02775);
  695. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  696. send_status(id, status);
  697. }
  698. else
  699. send_status(id, 3);
  700. xfree(name);
  701. }
  702. static void
  703. process_rmdir(void)
  704. {
  705. u_int32_t id;
  706. char *name;
  707. int ret, status;
  708. id = get_int();
  709. name = get_string(NULL);
  710. TRACE("rmdir id %u name %s", id, name);
  711. if (regex_match(ARCHIVE_PATH, name))
  712. {
  713. sec_log("\"%s\" directory removed.", name);
  714. ret = rmdir(name);
  715. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  716. send_status(id, status);
  717. }
  718. else
  719. send_status(id, 3);
  720. xfree(name);
  721. }
  722. static void
  723. process_realpath(void)
  724. {
  725. char resolvedname[MAXPATHLEN];
  726. u_int32_t id;
  727. char *path;
  728. id = get_int();
  729. path = get_string(NULL);
  730. if (path[0] == '\0') {
  731. xfree(path);
  732. path = xstrdup(".");
  733. }
  734. TRACE("realpath id %u path %s", id, path);
  735. if (realpath(path, resolvedname) == NULL) {
  736. send_status(id, errno_to_portable(errno));
  737. } else {
  738. Stat s;
  739. attrib_clear(&s.attrib);
  740. s.name = s.long_name = resolvedname;
  741. send_names(id, 1, &s);
  742. }
  743. xfree(path);
  744. }
  745. static void
  746. process_rename(void)
  747. {
  748. u_int32_t id;
  749. char *oldpath, *newpath;
  750. int status;
  751. struct stat sb;
  752. id = get_int();
  753. oldpath = get_string(NULL);
  754. newpath = get_string(NULL);
  755. TRACE("request to rename id %u old %s new %s", id, oldpath, newpath);
  756. sec_log("\"%s\" renamed to \"%s\".", oldpath, newpath);
  757. if (regex_match(ARCHIVE_PATH, newpath))
  758. {
  759. status = SSH2_FX_FAILURE;
  760. if (lstat(oldpath, &sb) == -1)
  761. status = errno_to_portable(errno);
  762. else if (S_ISREG(sb.st_mode)) {
  763. /* Race-free rename of regular files */
  764. if (link(oldpath, newpath) == -1)
  765. status = errno_to_portable(errno);
  766. else if (unlink(oldpath) == -1) {
  767. status = errno_to_portable(errno);
  768. /* clean spare link */
  769. unlink(newpath);
  770. } else
  771. status = SSH2_FX_OK;
  772. } else if (stat(newpath, &sb) == -1) {
  773. if (rename(oldpath, newpath) == -1)
  774. status = errno_to_portable(errno);
  775. else
  776. {
  777. status = SSH2_FX_OK;
  778. #ifdef COMMIT_NOTICE
  779. sec_log("commit notice program triggered.");
  780. if (fork()==0)
  781. {
  782. execl(COMMIT_NOTICE, COMMIT_NOTICE, newpath, (char*)0);
  783. exit(1);
  784. }
  785. #endif
  786. }
  787. }
  788. }
  789. else
  790. {
  791. status = 3; //permission denied
  792. sec_log("failed to rename \"%s\" to \"%s\".", oldpath, newpath);
  793. }
  794. send_status(id, status);
  795. xfree(oldpath);
  796. xfree(newpath);
  797. }
  798. static void
  799. process_readlink(void)
  800. {
  801. u_int32_t id;
  802. int len;
  803. char link[MAXPATHLEN];
  804. char *path;
  805. id = get_int();
  806. path = get_string(NULL);
  807. TRACE("readlink id %u path %s", id, path);
  808. if ((len = readlink(path, link, sizeof(link) - 1)) == -1)
  809. send_status(id, errno_to_portable(errno));
  810. else {
  811. Stat s;
  812. link[len] = '\0';
  813. attrib_clear(&s.attrib);
  814. s.name = s.long_name = link;
  815. send_names(id, 1, &s);
  816. }
  817. xfree(path);
  818. }
  819. static void
  820. process_symlink(void)
  821. {
  822. u_int32_t id;
  823. char *oldpath, *newpath;
  824. int ret, status;
  825. id = get_int();
  826. oldpath = get_string(NULL);
  827. newpath = get_string(NULL);
  828. TRACE("symlink id %u old %s new %s", id, oldpath, newpath);
  829. if (regex_match(ARCHIVE_PATH, newpath))
  830. {
  831. /* this will fail if 'newpath' exists */
  832. ret = symlink(oldpath, newpath);
  833. status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  834. send_status(id, status);
  835. }
  836. else
  837. send_status(id, 3);
  838. xfree(oldpath);
  839. xfree(newpath);
  840. }
  841. static void
  842. process_extended(void)
  843. {
  844. u_int32_t id;
  845. char *request;
  846. id = get_int();
  847. request = get_string(NULL);
  848. send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
  849. xfree(request);
  850. }
  851. /* stolen from ssh-agent */
  852. static void
  853. process(void)
  854. {
  855. u_int msg_len;
  856. u_int buf_len;
  857. u_int consumed;
  858. u_int type;
  859. u_char *cp;
  860. buf_len = buffer_len(&iqueue);
  861. if (buf_len < 5)
  862. return; /* Incomplete message. */
  863. cp = buffer_ptr(&iqueue);
  864. msg_len = GET_32BIT(cp);
  865. if (msg_len > 256 * 1024) {
  866. error("bad message ");
  867. exit(11);
  868. }
  869. if (buf_len < msg_len + 4)
  870. return;
  871. buffer_consume(&iqueue, 4);
  872. buf_len -= 4;
  873. type = buffer_get_char(&iqueue);
  874. switch (type) {
  875. case SSH2_FXP_INIT:
  876. process_init();
  877. break;
  878. case SSH2_FXP_OPEN:
  879. process_open();
  880. break;
  881. case SSH2_FXP_CLOSE:
  882. process_close();
  883. break;
  884. case SSH2_FXP_READ:
  885. process_read();
  886. break;
  887. case SSH2_FXP_WRITE:
  888. process_write();
  889. break;
  890. case SSH2_FXP_LSTAT:
  891. process_lstat();
  892. break;
  893. case SSH2_FXP_FSTAT:
  894. process_fstat();
  895. break;
  896. case SSH2_FXP_SETSTAT:
  897. process_setstat();
  898. break;
  899. case SSH2_FXP_FSETSTAT:
  900. process_fsetstat();
  901. break;
  902. case SSH2_FXP_OPENDIR:
  903. process_opendir();
  904. break;
  905. case SSH2_FXP_READDIR:
  906. process_readdir();
  907. break;
  908. case SSH2_FXP_REMOVE:
  909. process_remove();
  910. break;
  911. case SSH2_FXP_MKDIR:
  912. process_mkdir();
  913. break;
  914. case SSH2_FXP_RMDIR:
  915. process_rmdir();
  916. break;
  917. case SSH2_FXP_REALPATH:
  918. process_realpath();
  919. break;
  920. case SSH2_FXP_STAT:
  921. process_stat();
  922. break;
  923. case SSH2_FXP_RENAME:
  924. process_rename();
  925. break;
  926. case SSH2_FXP_READLINK:
  927. process_readlink();
  928. break;
  929. case SSH2_FXP_SYMLINK:
  930. process_symlink();
  931. break;
  932. case SSH2_FXP_EXTENDED:
  933. process_extended();
  934. break;
  935. default:
  936. error("Unknown message %d", type);
  937. break;
  938. }
  939. /* discard the remaining bytes from the current packet */
  940. if (buf_len < buffer_len(&iqueue))
  941. fatal("iqueue grows");
  942. consumed = buf_len - buffer_len(&iqueue);
  943. if (msg_len < consumed)
  944. fatal("msg_len %d < consumed %d", msg_len, consumed);
  945. if (msg_len > consumed)
  946. buffer_consume(&iqueue, msg_len - consumed);
  947. }
  948. int
  949. main(int ac, char **av)
  950. {
  951. fd_set *rset, *wset;
  952. int in, out, max;
  953. ssize_t len, olen, set_size;
  954. password_data = getpwuid(getuid());
  955. /* XXX should use getopt */
  956. __progname = ssh_get_progname(av[0]);
  957. handle_init();
  958. #ifdef DEBUG_SFTP_SERVER
  959. log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
  960. #endif
  961. in = dup(STDIN_FILENO);
  962. out = dup(STDOUT_FILENO);
  963. #ifdef HAVE_CYGWIN
  964. setmode(in, O_BINARY);
  965. setmode(out, O_BINARY);
  966. #endif
  967. max = 0;
  968. if (in > max)
  969. max = in;
  970. if (out > max)
  971. max = out;
  972. buffer_init(&iqueue);
  973. buffer_init(&oqueue);
  974. set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
  975. rset = (fd_set *)xmalloc(set_size);
  976. wset = (fd_set *)xmalloc(set_size);
  977. for (;;) {
  978. memset(rset, 0, set_size);
  979. memset(wset, 0, set_size);
  980. FD_SET(in, rset);
  981. olen = buffer_len(&oqueue);
  982. if (olen > 0)
  983. FD_SET(out, wset);
  984. if (select(max+1, rset, wset, NULL, NULL) < 0) {
  985. if (errno == EINTR)
  986. continue;
  987. exit(2);
  988. }
  989. /* copy stdin to iqueue */
  990. if (FD_ISSET(in, rset)) {
  991. char buf[4*4096];
  992. len = read(in, buf, sizeof buf);
  993. if (len == 0) {
  994. debug("read eof");
  995. exit(0);
  996. } else if (len < 0) {
  997. error("read error");
  998. exit(1);
  999. } else {
  1000. buffer_append(&iqueue, buf, len);
  1001. }
  1002. }
  1003. /* send oqueue to stdout */
  1004. if (FD_ISSET(out, wset)) {
  1005. len = write(out, buffer_ptr(&oqueue), olen);
  1006. if (len < 0) {
  1007. error("write error");
  1008. exit(1);
  1009. } else {
  1010. buffer_consume(&oqueue, len);
  1011. }
  1012. }
  1013. /* process requests from client */
  1014. process();
  1015. }
  1016. }