PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

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

#
Patch | 475 lines | 458 code | 17 blank | 0 comment | 0 complexity | 3f39e186f11d5331a95277ad44cce56f MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
  1. --- ./sftp-server.c 2004-02-23 17:19:15.000000000 -0500
  2. +++ /home/mjflick/gnu/arch-subsystem/sftp-server.c 2005-12-11 16:54:03.000000000 -0500
  3. @@ -16,15 +16,38 @@
  4. #include "includes.h"
  5. RCSID("$OpenBSD: sftp-server.c,v 1.45 2004/02/19 21:15:04 markus Exp $");
  6. +/*
  7. + * Patched for GNU Arch support 2005.
  8. + * Patch released under public domain.
  9. + * 2005 - Michael J. Flickinger
  10. + */
  11. +
  12. #include "buffer.h"
  13. #include "bufaux.h"
  14. #include "getput.h"
  15. #include "log.h"
  16. #include "xmalloc.h"
  17. +#include <sys/types.h>
  18. +#include <sys/file.h>
  19. +#include <sys/stat.h>
  20. +#include <syslog.h>
  21. +#include <unistd.h>
  22. +#include <time.h>
  23. +#include <stdio.h>
  24. +#include <stdlib.h>
  25. +#include <regex.h>
  26. +
  27. +#include <fcntl.h>
  28. +#include <pwd.h>
  29. +
  30. #include "sftp.h"
  31. #include "sftp-common.h"
  32. +#define SEAL_ARCHIVES "/utils/seal-archives"
  33. +#define ARCHIVE_PATH "^/archives/|^/srv/arch/" // path, (regex)
  34. +#define COMMIT_NOTICE "/utils/mail-on-commit.pl" // comment out if not desired
  35. +
  36. /* helper */
  37. #define get_int64() buffer_get_int64(&iqueue);
  38. #define get_int() buffer_get_int(&iqueue);
  39. @@ -54,6 +77,45 @@ struct Stat {
  40. Attrib attrib;
  41. };
  42. +struct passwd *password_data;
  43. +
  44. +
  45. +static void
  46. +sec_log (char *message, ...)
  47. +{
  48. + va_list args;
  49. + char msgbuf[2048];
  50. +
  51. + char *connection = getenv("SSH_CLIENT");
  52. +
  53. + va_start(args, message);
  54. + vsnprintf(msgbuf, sizeof(msgbuf), message, args);
  55. +
  56. + setlogmask (LOG_UPTO (LOG_NOTICE));
  57. + openlog ("sftp-server", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
  58. + syslog(LOG_NOTICE, "user: %s -- uid: %i -- from: %s -- %s\n", password_data->pw_name, getuid(), connection, msgbuf);
  59. + closelog ();
  60. +
  61. + va_end(args);
  62. +}
  63. +
  64. +static int
  65. +regex_match (char *pat, const char* string)
  66. +{
  67. + int result;
  68. + regex_t re;
  69. +
  70. + if (regcomp(&re, pat, REG_EXTENDED|REG_NOSUB) != 0)
  71. + return(-1);
  72. +
  73. + result = regexec(&re, string, (size_t) 0, NULL, 0);
  74. + regfree(&re);
  75. + if (result != 0)
  76. + return(0);
  77. +
  78. + return(1);
  79. +}
  80. +
  81. static int
  82. errno_to_portable(int unixerrno)
  83. {
  84. @@ -138,6 +200,8 @@ handle_init(void)
  85. for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
  86. handles[i].use = HANDLE_UNUSED;
  87. +
  88. + sec_log("login to arch sftp subsystem");
  89. }
  90. static int
  91. @@ -386,20 +450,32 @@ process_open(void)
  92. flags = flags_from_portable(pflags);
  93. mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
  94. TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode);
  95. - fd = open(name, flags, mode);
  96. - if (fd < 0) {
  97. - status = errno_to_portable(errno);
  98. - } else {
  99. - handle = handle_new(HANDLE_FILE, name, fd, NULL);
  100. - if (handle < 0) {
  101. - close(fd);
  102. - } else {
  103. - send_handle(id, handle);
  104. - status = SSH2_FX_OK;
  105. - }
  106. - }
  107. - if (status != SSH2_FX_OK)
  108. - send_status(id, status);
  109. +
  110. + if (regex_match(ARCHIVE_PATH, name))
  111. + {
  112. + if (pflags == 1)
  113. + sec_log("\"%s\" opened for reading.", name);
  114. + else
  115. + sec_log("\"%s\" opened for writing.", name);
  116. +
  117. + fd = open(name, flags, mode);
  118. + if (fd < 0) {
  119. + status = errno_to_portable(errno);
  120. + } else {
  121. + handle = handle_new(HANDLE_FILE, name, fd, NULL);
  122. + if (handle < 0) {
  123. + close(fd);
  124. + } else {
  125. + send_handle(id, handle);
  126. + status = SSH2_FX_OK;
  127. + }
  128. + }
  129. + if (status != SSH2_FX_OK)
  130. + send_status(id, status);
  131. + }
  132. + else
  133. + send_status(id, 3);
  134. +
  135. xfree(name);
  136. }
  137. @@ -465,6 +541,7 @@ process_write(void)
  138. u_int len;
  139. int handle, fd, ret, status = SSH2_FX_FAILURE;
  140. char *data;
  141. + char *name;
  142. id = get_int();
  143. handle = get_handle();
  144. @@ -474,6 +551,7 @@ process_write(void)
  145. TRACE("write id %u handle %d off %llu len %d", id, handle,
  146. (u_int64_t)off, len);
  147. fd = handle_to_fd(handle);
  148. + name = handle_to_name(handle);
  149. if (fd >= 0) {
  150. if (lseek(fd, off, SEEK_SET) < 0) {
  151. status = errno_to_portable(errno);
  152. @@ -491,6 +569,17 @@ process_write(void)
  153. }
  154. }
  155. }
  156. +
  157. + chmod(name, 0664);
  158. +
  159. + sec_log("sealing: \"%s\"", name);
  160. +
  161. + if (fork()==0)
  162. + {
  163. + execl(SEAL_ARCHIVES, SEAL_ARCHIVES, name, (char*)0);
  164. + exit(1);
  165. + }
  166. +
  167. send_status(id, status);
  168. xfree(data);
  169. }
  170. @@ -558,106 +647,22 @@ process_fstat(void)
  171. send_status(id, status);
  172. }
  173. -static struct timeval *
  174. -attrib_to_tv(const Attrib *a)
  175. -{
  176. - static struct timeval tv[2];
  177. -
  178. - tv[0].tv_sec = a->atime;
  179. - tv[0].tv_usec = 0;
  180. - tv[1].tv_sec = a->mtime;
  181. - tv[1].tv_usec = 0;
  182. - return tv;
  183. -}
  184. -
  185. static void
  186. process_setstat(void)
  187. {
  188. - Attrib *a;
  189. u_int32_t id;
  190. - char *name;
  191. - int status = SSH2_FX_OK, ret;
  192. -
  193. id = get_int();
  194. - name = get_string(NULL);
  195. - a = get_attrib();
  196. - TRACE("setstat id %u name %s", id, name);
  197. - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
  198. - ret = truncate(name, a->size);
  199. - if (ret == -1)
  200. - status = errno_to_portable(errno);
  201. - }
  202. - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
  203. - ret = chmod(name, a->perm & 0777);
  204. - if (ret == -1)
  205. - status = errno_to_portable(errno);
  206. - }
  207. - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
  208. - ret = utimes(name, attrib_to_tv(a));
  209. - if (ret == -1)
  210. - status = errno_to_portable(errno);
  211. - }
  212. - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
  213. - ret = chown(name, a->uid, a->gid);
  214. - if (ret == -1)
  215. - status = errno_to_portable(errno);
  216. - }
  217. - send_status(id, status);
  218. - xfree(name);
  219. +
  220. + send_status(id, 0);
  221. }
  222. static void
  223. process_fsetstat(void)
  224. {
  225. - Attrib *a;
  226. u_int32_t id;
  227. - int handle, fd, ret;
  228. - int status = SSH2_FX_OK;
  229. - char *name;
  230. -
  231. id = get_int();
  232. - handle = get_handle();
  233. - a = get_attrib();
  234. - TRACE("fsetstat id %u handle %d", id, handle);
  235. - fd = handle_to_fd(handle);
  236. - name = handle_to_name(handle);
  237. - if (fd < 0 || name == NULL) {
  238. - status = SSH2_FX_FAILURE;
  239. - } else {
  240. - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
  241. - ret = ftruncate(fd, a->size);
  242. - if (ret == -1)
  243. - status = errno_to_portable(errno);
  244. - }
  245. - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
  246. -#ifdef HAVE_FCHMOD
  247. - ret = fchmod(fd, a->perm & 0777);
  248. -#else
  249. - ret = chmod(name, a->perm & 0777);
  250. -#endif
  251. - if (ret == -1)
  252. - status = errno_to_portable(errno);
  253. - }
  254. - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
  255. -#ifdef HAVE_FUTIMES
  256. - ret = futimes(fd, attrib_to_tv(a));
  257. -#else
  258. - ret = utimes(name, attrib_to_tv(a));
  259. -#endif
  260. - if (ret == -1)
  261. - status = errno_to_portable(errno);
  262. - }
  263. - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
  264. -#ifdef HAVE_FCHOWN
  265. - ret = fchown(fd, a->uid, a->gid);
  266. -#else
  267. - ret = chown(name, a->uid, a->gid);
  268. -#endif
  269. - if (ret == -1)
  270. - status = errno_to_portable(errno);
  271. - }
  272. - }
  273. - send_status(id, status);
  274. +
  275. + send_status(id, 0);
  276. }
  277. static void
  278. @@ -750,15 +755,25 @@ process_remove(void)
  279. char *name;
  280. u_int32_t id;
  281. int status = SSH2_FX_FAILURE;
  282. - int ret;
  283. + int ret;
  284. id = get_int();
  285. name = get_string(NULL);
  286. TRACE("remove id %u name %s", id, name);
  287. - ret = unlink(name);
  288. - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  289. - send_status(id, status);
  290. - xfree(name);
  291. +
  292. + if (regex_match(ARCHIVE_PATH, name))
  293. + {
  294. + ret = unlink(name);
  295. + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  296. + if (ret != -1)
  297. + sec_log("removed \"%s\"", name);
  298. +
  299. + send_status(id, status);
  300. + }
  301. + else
  302. + send_status(id, 3);
  303. +
  304. + xfree(name);
  305. }
  306. static void
  307. @@ -775,9 +790,23 @@ process_mkdir(void)
  308. mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
  309. a->perm & 0777 : 0777;
  310. TRACE("mkdir id %u name %s mode 0%o", id, name, mode);
  311. - ret = mkdir(name, mode);
  312. - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  313. - send_status(id, status);
  314. +
  315. + if (regex_match(ARCHIVE_PATH, name))
  316. + {
  317. + sec_log("\"%s\" directory created.", name);
  318. +
  319. + ret = mkdir(name, 02775);
  320. + sec_log("creating directory: %s\n", name);
  321. +
  322. + if (ret != -1)
  323. + ret = chmod(name, 02775);
  324. +
  325. + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  326. + send_status(id, status);
  327. + }
  328. + else
  329. + send_status(id, 3);
  330. +
  331. xfree(name);
  332. }
  333. @@ -791,10 +820,19 @@ process_rmdir(void)
  334. id = get_int();
  335. name = get_string(NULL);
  336. TRACE("rmdir id %u name %s", id, name);
  337. - ret = rmdir(name);
  338. - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  339. - send_status(id, status);
  340. - xfree(name);
  341. +
  342. + if (regex_match(ARCHIVE_PATH, name))
  343. + {
  344. + sec_log("\"%s\" directory removed.", name);
  345. +
  346. + ret = rmdir(name);
  347. + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  348. + send_status(id, status);
  349. + }
  350. + else
  351. + send_status(id, 3);
  352. +
  353. + xfree(name);
  354. }
  355. static void
  356. @@ -833,26 +871,54 @@ process_rename(void)
  357. id = get_int();
  358. oldpath = get_string(NULL);
  359. newpath = get_string(NULL);
  360. - TRACE("rename id %u old %s new %s", id, oldpath, newpath);
  361. - status = SSH2_FX_FAILURE;
  362. - if (lstat(oldpath, &sb) == -1)
  363. + TRACE("request to rename id %u old %s new %s", id, oldpath, newpath);
  364. +
  365. + sec_log("\"%s\" renamed to \"%s\".", oldpath, newpath);
  366. +
  367. + if (regex_match(ARCHIVE_PATH, newpath))
  368. + {
  369. + status = SSH2_FX_FAILURE;
  370. + if (lstat(oldpath, &sb) == -1)
  371. + status = errno_to_portable(errno);
  372. + else if (S_ISREG(sb.st_mode)) {
  373. + /* Race-free rename of regular files */
  374. + if (link(oldpath, newpath) == -1)
  375. status = errno_to_portable(errno);
  376. - else if (S_ISREG(sb.st_mode)) {
  377. - /* Race-free rename of regular files */
  378. - if (link(oldpath, newpath) == -1)
  379. - status = errno_to_portable(errno);
  380. - else if (unlink(oldpath) == -1) {
  381. - status = errno_to_portable(errno);
  382. - /* clean spare link */
  383. - unlink(newpath);
  384. - } else
  385. - status = SSH2_FX_OK;
  386. - } else if (stat(newpath, &sb) == -1) {
  387. - if (rename(oldpath, newpath) == -1)
  388. - status = errno_to_portable(errno);
  389. - else
  390. - status = SSH2_FX_OK;
  391. - }
  392. + else if (unlink(oldpath) == -1) {
  393. + status = errno_to_portable(errno);
  394. + /* clean spare link */
  395. + unlink(newpath);
  396. + } else
  397. + status = SSH2_FX_OK;
  398. + } else if (stat(newpath, &sb) == -1) {
  399. + if (rename(oldpath, newpath) == -1)
  400. + status = errno_to_portable(errno);
  401. + else
  402. + {
  403. + status = SSH2_FX_OK;
  404. +
  405. +#ifdef COMMIT_NOTICE
  406. + sec_log("commit notice program triggered.");
  407. +
  408. + if (fork()==0)
  409. + {
  410. + execl(COMMIT_NOTICE, COMMIT_NOTICE, newpath, (char*)0);
  411. + exit(1);
  412. + }
  413. +#endif
  414. +
  415. + }
  416. + }
  417. +
  418. +
  419. + }
  420. + else
  421. + {
  422. + status = 3; //permission denied
  423. + sec_log("failed to rename \"%s\" to \"%s\".", oldpath, newpath);
  424. + }
  425. +
  426. +
  427. send_status(id, status);
  428. xfree(oldpath);
  429. xfree(newpath);
  430. @@ -893,10 +959,17 @@ process_symlink(void)
  431. oldpath = get_string(NULL);
  432. newpath = get_string(NULL);
  433. TRACE("symlink id %u old %s new %s", id, oldpath, newpath);
  434. - /* this will fail if 'newpath' exists */
  435. - ret = symlink(oldpath, newpath);
  436. - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  437. - send_status(id, status);
  438. +
  439. + if (regex_match(ARCHIVE_PATH, newpath))
  440. + {
  441. + /* this will fail if 'newpath' exists */
  442. + ret = symlink(oldpath, newpath);
  443. + status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
  444. + send_status(id, status);
  445. + }
  446. + else
  447. + send_status(id, 3);
  448. +
  449. xfree(oldpath);
  450. xfree(newpath);
  451. }
  452. @@ -1020,6 +1093,8 @@ main(int ac, char **av)
  453. int in, out, max;
  454. ssize_t len, olen, set_size;
  455. + password_data = getpwuid(getuid());
  456. +
  457. /* XXX should use getopt */
  458. __progname = ssh_get_progname(av[0]);