ftppolicy.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Part of Very Secure FTPd
  3. * Licence: GPL v2
  4. * Author: Chris Evans
  5. * ftppolicy.c
  6. *
  7. * Code to build a sandbox policy based on current session options.
  8. */
  9. #include "ftppolicy.h"
  10. #include "ptracesandbox.h"
  11. #include "tunables.h"
  12. #include "session.h"
  13. #include "sysutil.h"
  14. /* For AF_INET etc. network constants. */
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <netinet/in_systm.h>
  18. #include <netinet/in.h>
  19. #include <netinet/ip.h>
  20. #include <netinet/tcp.h>
  21. static int socket_validator(struct pt_sandbox* p_sandbox, void* p_arg);
  22. static int connect_validator(struct pt_sandbox* p_sandbox, void* p_arg);
  23. static int getsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg);
  24. static int setsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg);
  25. void
  26. policy_setup(struct pt_sandbox* p_sandbox, const struct vsf_session* p_sess)
  27. {
  28. int is_anon = p_sess->is_anonymous;
  29. /* Always need to be able to exit! */
  30. ptrace_sandbox_permit_exit(p_sandbox);
  31. /* Needed for memory management. */
  32. ptrace_sandbox_permit_mmap(p_sandbox);
  33. ptrace_sandbox_permit_mprotect(p_sandbox);
  34. ptrace_sandbox_permit_brk(p_sandbox);
  35. /* Simple reads and writes are required. Permitting write does not imply
  36. * filesystem write access because access control is done at open time.
  37. */
  38. ptrace_sandbox_permit_read(p_sandbox);
  39. ptrace_sandbox_permit_write(p_sandbox);
  40. /* Reading FTP commands from the network. */
  41. ptrace_sandbox_permit_recv(p_sandbox);
  42. /* Querying time is harmless; used for log timestamps and internally to
  43. * OpenSSL
  44. */
  45. ptrace_sandbox_permit_query_time(p_sandbox);
  46. /* Typically post-login things follow. */
  47. /* Since we're in a chroot(), we can just blanket allow filesystem readonly
  48. * open.
  49. */
  50. ptrace_sandbox_permit_open(p_sandbox, 0);
  51. ptrace_sandbox_permit_close(p_sandbox);
  52. /* Other pathname-based metadata queries. */
  53. ptrace_sandbox_permit_file_stats(p_sandbox);
  54. ptrace_sandbox_permit_readlink(p_sandbox);
  55. /* Querying, reading and changing directory. */
  56. ptrace_sandbox_permit_getcwd(p_sandbox);
  57. ptrace_sandbox_permit_chdir(p_sandbox);
  58. ptrace_sandbox_permit_getdents(p_sandbox);
  59. /* Simple fd-based operations. */
  60. ptrace_sandbox_permit_fd_stats(p_sandbox);
  61. ptrace_sandbox_permit_seek(p_sandbox);
  62. ptrace_sandbox_permit_shutdown(p_sandbox);
  63. ptrace_sandbox_permit_fcntl(p_sandbox);
  64. ptrace_sandbox_permit_setsockopt(p_sandbox);
  65. ptrace_sandbox_set_setsockopt_validator(p_sandbox, setsockopt_validator, 0);
  66. /* Misc */
  67. /* Setting umask. */
  68. ptrace_sandbox_permit_umask(p_sandbox);
  69. /* Select for data connection readyness. */
  70. ptrace_sandbox_permit_select(p_sandbox);
  71. /* Always need ability to take signals (SIGPIPE) */
  72. ptrace_sandbox_permit_sigreturn(p_sandbox);
  73. /* Sleeping (bandwidth limit, connect retires, anon login fails) */
  74. ptrace_sandbox_permit_sleep(p_sandbox);
  75. /* High-speed transfers... */
  76. ptrace_sandbox_permit_sendfile(p_sandbox);
  77. /* TODO - Grrrr! nscd cache access is leaking into child. Need to find out
  78. * out how to disable that. Also means that text_userdb_names loads values
  79. * from the real system data.
  80. */
  81. if (tunable_text_userdb_names)
  82. {
  83. ptrace_sandbox_permit_mremap(p_sandbox);
  84. }
  85. /* May need ability to install signal handlers. */
  86. if (tunable_async_abor_enable ||
  87. tunable_idle_session_timeout > 0 ||
  88. tunable_data_connection_timeout > 0)
  89. {
  90. ptrace_sandbox_permit_sigaction(p_sandbox);
  91. }
  92. /* May need ability to set up timeout alarms. */
  93. if (tunable_idle_session_timeout > 0 || tunable_data_connection_timeout > 0)
  94. {
  95. ptrace_sandbox_permit_alarm(p_sandbox);
  96. }
  97. /* Set up network permissions according to config and session. */
  98. ptrace_sandbox_permit_socket(p_sandbox);
  99. ptrace_sandbox_set_socket_validator(p_sandbox,
  100. socket_validator,
  101. (void*) p_sess);
  102. ptrace_sandbox_permit_bind(p_sandbox);
  103. /* Yes, reuse of the connect validator is intentional. */
  104. ptrace_sandbox_set_bind_validator(p_sandbox,
  105. connect_validator,
  106. (void*) p_sess);
  107. if (tunable_port_enable)
  108. {
  109. ptrace_sandbox_permit_connect(p_sandbox);
  110. ptrace_sandbox_set_connect_validator(p_sandbox,
  111. connect_validator,
  112. (void*) p_sess);
  113. ptrace_sandbox_permit_getsockopt(p_sandbox);
  114. ptrace_sandbox_set_getsockopt_validator(p_sandbox, getsockopt_validator, 0);
  115. }
  116. if (tunable_pasv_enable)
  117. {
  118. ptrace_sandbox_permit_listen(p_sandbox);
  119. ptrace_sandbox_permit_accept(p_sandbox);
  120. }
  121. /* Set up write permissions according to config and session. */
  122. if (tunable_write_enable)
  123. {
  124. if (!is_anon || tunable_anon_upload_enable)
  125. {
  126. ptrace_sandbox_permit_open(p_sandbox, 1);
  127. }
  128. if (!is_anon || tunable_anon_mkdir_write_enable)
  129. {
  130. ptrace_sandbox_permit_mkdir(p_sandbox);
  131. }
  132. if (!is_anon || tunable_anon_other_write_enable)
  133. {
  134. ptrace_sandbox_permit_unlink(p_sandbox);
  135. ptrace_sandbox_permit_rmdir(p_sandbox);
  136. ptrace_sandbox_permit_rename(p_sandbox);
  137. ptrace_sandbox_permit_ftruncate(p_sandbox);
  138. if (tunable_mdtm_write)
  139. {
  140. ptrace_sandbox_permit_utime(p_sandbox);
  141. }
  142. }
  143. if (!is_anon && tunable_chmod_enable)
  144. {
  145. ptrace_sandbox_permit_chmod(p_sandbox);
  146. }
  147. if (is_anon && tunable_chown_uploads)
  148. {
  149. ptrace_sandbox_permit_fchmod(p_sandbox);
  150. ptrace_sandbox_permit_fchown(p_sandbox);
  151. }
  152. }
  153. }
  154. static int
  155. socket_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  156. {
  157. int ret;
  158. struct vsf_session* p_sess = (struct vsf_session*) p_arg;
  159. unsigned long arg1;
  160. unsigned long arg2;
  161. unsigned long expected_family = AF_INET;
  162. if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
  163. {
  164. expected_family = AF_INET6;
  165. }
  166. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 0, &arg1);
  167. if (ret != 0)
  168. {
  169. return ret;
  170. }
  171. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  172. if (ret != 0)
  173. {
  174. return ret;
  175. }
  176. if (arg1 != expected_family || arg2 != SOCK_STREAM)
  177. {
  178. return -1;
  179. }
  180. return 0;
  181. }
  182. static int
  183. connect_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  184. {
  185. int ret;
  186. struct vsf_session* p_sess = (struct vsf_session*) p_arg;
  187. unsigned long arg2;
  188. unsigned long arg3;
  189. unsigned long expected_family = AF_INET;
  190. unsigned long expected_len = sizeof(struct sockaddr_in);
  191. void* p_buf = 0;
  192. struct sockaddr* p_sockaddr;
  193. static struct vsf_sysutil_sockaddr* p_sockptr;
  194. if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
  195. {
  196. expected_family = AF_INET6;
  197. expected_len = sizeof(struct sockaddr_in6);
  198. }
  199. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  200. if (ret != 0)
  201. {
  202. return ret;
  203. }
  204. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
  205. if (ret != 0)
  206. {
  207. return ret;
  208. }
  209. if (arg3 != expected_len)
  210. {
  211. return -1;
  212. }
  213. p_buf = vsf_sysutil_malloc((int) expected_len);
  214. ret = ptrace_sandbox_get_buf(p_sandbox, arg2, expected_len, p_buf);
  215. if (ret != 0)
  216. {
  217. vsf_sysutil_free(p_buf);
  218. return -2;
  219. }
  220. p_sockaddr = (struct sockaddr*) p_buf;
  221. if (p_sockaddr->sa_family != expected_family)
  222. {
  223. vsf_sysutil_free(p_buf);
  224. return -3;
  225. }
  226. if (expected_family == AF_INET)
  227. {
  228. struct sockaddr_in* p_sockaddr_in = (struct sockaddr_in*) p_sockaddr;
  229. vsf_sysutil_sockaddr_alloc_ipv4(&p_sockptr);
  230. vsf_sysutil_sockaddr_set_ipv4addr(p_sockptr,
  231. (const unsigned char*)
  232. &p_sockaddr_in->sin_addr);
  233. }
  234. else
  235. {
  236. struct sockaddr_in6* p_sockaddr_in6 = (struct sockaddr_in6*) p_sockaddr;
  237. vsf_sysutil_sockaddr_alloc_ipv6(&p_sockptr);
  238. vsf_sysutil_sockaddr_set_ipv6addr(p_sockptr,
  239. (const unsigned char*)
  240. &p_sockaddr_in6->sin6_addr);
  241. }
  242. if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_sockptr))
  243. {
  244. vsf_sysutil_free(p_buf);
  245. return -4;
  246. }
  247. vsf_sysutil_free(p_buf);
  248. return 0;
  249. }
  250. static int
  251. getsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  252. {
  253. int ret;
  254. unsigned long arg2;
  255. unsigned long arg3;
  256. (void) p_arg;
  257. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  258. if (ret != 0)
  259. {
  260. return ret;
  261. }
  262. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
  263. if (ret != 0)
  264. {
  265. return ret;
  266. }
  267. if (arg2 != SOL_SOCKET || arg3 != SO_ERROR)
  268. {
  269. return -1;
  270. }
  271. return 0;
  272. }
  273. static int
  274. setsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  275. {
  276. int ret;
  277. unsigned long arg2;
  278. unsigned long arg3;
  279. (void) p_arg;
  280. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  281. if (ret != 0)
  282. {
  283. return ret;
  284. }
  285. ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
  286. if (ret != 0)
  287. {
  288. return ret;
  289. }
  290. if (arg2 == SOL_SOCKET)
  291. {
  292. if (arg3 != SO_KEEPALIVE &&
  293. arg3 != SO_REUSEADDR &&
  294. arg3 != SO_OOBINLINE &&
  295. arg3 != SO_LINGER)
  296. {
  297. return -1;
  298. }
  299. }
  300. else if (arg2 == IPPROTO_TCP)
  301. {
  302. if (arg3 != TCP_NODELAY)
  303. {
  304. return -2;
  305. }
  306. }
  307. else if (arg2 == IPPROTO_IP)
  308. {
  309. if (arg3 != IP_TOS)
  310. {
  311. return -3;
  312. }
  313. }
  314. else
  315. {
  316. return -4;
  317. }
  318. return 0;
  319. }