ftppolicy.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:9k
源码类别:

Ftp客户端

开发平台:

C/C++

  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.   /* Querying time is harmless; used for log timestamps and internally to
  41.    * OpenSSL
  42.    */
  43.   ptrace_sandbox_permit_query_time(p_sandbox);
  44.   /* Stat'ing is needed for downloading and directory listings. Can blanket
  45.    * enable for any filename thanks to the chroot().
  46.    */
  47.   ptrace_sandbox_permit_file_stats(p_sandbox);
  48.   ptrace_sandbox_permit_fd_stats(p_sandbox);
  49.   /* Querying and changing directory. */
  50.   ptrace_sandbox_permit_getcwd(p_sandbox);
  51.   ptrace_sandbox_permit_chdir(p_sandbox);
  52.   /* Setting umask. */
  53.   ptrace_sandbox_permit_umask(p_sandbox);
  54.   /* Since we're in a chroot(), we can just blanket allow filesystem readonly
  55.    * open.
  56.    */
  57.   ptrace_sandbox_permit_open(p_sandbox, 0);
  58.   ptrace_sandbox_permit_close(p_sandbox);
  59.   /* High-speed transfers... */
  60.   ptrace_sandbox_permit_sendfile(p_sandbox);
  61.   /* Reading directories. */
  62.   ptrace_sandbox_permit_getdents(p_sandbox);
  63.   /* Reading symlink targets. */
  64.   ptrace_sandbox_permit_readlink(p_sandbox);
  65.   /* File locking. */
  66.   ptrace_sandbox_permit_fcntl(p_sandbox);
  67.   /* Seeking for REST. */
  68.   ptrace_sandbox_permit_seek(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.   /* May need ability to install signal handlers. */
  76.   if (tunable_async_abor_enable ||
  77.       tunable_idle_session_timeout > 0 ||
  78.       tunable_data_connection_timeout > 0)
  79.   {
  80.     ptrace_sandbox_permit_sigaction(p_sandbox);
  81.   }
  82.   /* May need ability to set up timeout alarms. */
  83.   if (tunable_idle_session_timeout > 0 || tunable_data_connection_timeout > 0)
  84.   {
  85.     ptrace_sandbox_permit_alarm(p_sandbox);
  86.   }
  87.   /* TODO - Grrrr! nscd cache access is leaking into child. Need to find out
  88.    * out how to disable that. Also means that text_userdb_names loads values
  89.    * from the real system data.
  90.    */
  91.   if (tunable_text_userdb_names)
  92.   {
  93.     ptrace_sandbox_permit_mremap(p_sandbox);
  94.   }
  95.   /* Set up network permissions according to config and session. */
  96.   ptrace_sandbox_permit_recv(p_sandbox);
  97.   ptrace_sandbox_permit_shutdown(p_sandbox);
  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.   ptrace_sandbox_permit_setsockopt(p_sandbox);
  108.   ptrace_sandbox_set_setsockopt_validator(p_sandbox, setsockopt_validator, 0);
  109.   ptrace_sandbox_permit_shutdown(p_sandbox);
  110.   if (tunable_port_enable)
  111.   {
  112.     ptrace_sandbox_permit_connect(p_sandbox);
  113.     ptrace_sandbox_set_connect_validator(p_sandbox,
  114.                                          connect_validator,
  115.                                          (void*) p_sess);
  116.     ptrace_sandbox_permit_getsockopt(p_sandbox);
  117.     ptrace_sandbox_set_getsockopt_validator(p_sandbox, getsockopt_validator, 0);
  118.   }
  119.   if (tunable_pasv_enable)
  120.   {
  121.     ptrace_sandbox_permit_listen(p_sandbox);
  122.     ptrace_sandbox_permit_accept(p_sandbox);
  123.   }
  124.   /* Set up write permissions according to config and session. */
  125.   if (tunable_write_enable)
  126.   {
  127.     if (!is_anon || tunable_anon_upload_enable)
  128.     {
  129.       ptrace_sandbox_permit_open(p_sandbox, 1);
  130.     }
  131.     if (!is_anon || tunable_anon_mkdir_write_enable)
  132.     {
  133.       ptrace_sandbox_permit_mkdir(p_sandbox);
  134.     }
  135.     if (!is_anon || tunable_anon_other_write_enable)
  136.     {
  137.       ptrace_sandbox_permit_unlink(p_sandbox);
  138.       ptrace_sandbox_permit_rmdir(p_sandbox);
  139.       ptrace_sandbox_permit_rename(p_sandbox);
  140.       ptrace_sandbox_permit_ftruncate(p_sandbox);
  141.       if (tunable_mdtm_write)
  142.       {
  143.         ptrace_sandbox_permit_utime(p_sandbox);
  144.       }
  145.     }
  146.     if (!is_anon && tunable_chmod_enable)
  147.     {
  148.       ptrace_sandbox_permit_chmod(p_sandbox);
  149.     }
  150.     if (is_anon && tunable_chown_uploads)
  151.     {
  152.       ptrace_sandbox_permit_fchmod(p_sandbox);
  153.       ptrace_sandbox_permit_fchown(p_sandbox);
  154.     }
  155.   }
  156. }
  157. static int
  158. socket_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  159. {
  160.   int ret;
  161.   struct vsf_session* p_sess = (struct vsf_session*) p_arg;
  162.   unsigned long arg1;
  163.   unsigned long arg2;
  164.   unsigned long expected_family = AF_INET;
  165.   if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
  166.   {
  167.     expected_family = AF_INET6;
  168.   }
  169.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 0, &arg1);
  170.   if (ret != 0)
  171.   {
  172.     return ret;
  173.   }
  174.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  175.   if (ret != 0)
  176.   {
  177.     return ret;
  178.   }
  179.   if (arg1 != expected_family || arg2 != SOCK_STREAM)
  180.   {
  181.     return -1;
  182.   }
  183.   return 0;
  184. }
  185. static int
  186. connect_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  187. {
  188.   int ret;
  189.   struct vsf_session* p_sess = (struct vsf_session*) p_arg;
  190.   unsigned long arg2;
  191.   unsigned long arg3;
  192.   unsigned long expected_family = AF_INET;
  193.   unsigned long expected_len = sizeof(struct sockaddr_in);
  194.   void* p_buf = 0;
  195.   struct sockaddr* p_sockaddr;
  196.   static struct vsf_sysutil_sockaddr* p_sockptr;
  197.   if (vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr))
  198.   {
  199.     expected_family = AF_INET6;
  200.     expected_len = sizeof(struct sockaddr_in6);
  201.   }
  202.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  203.   if (ret != 0)
  204.   {
  205.     return ret;
  206.   }
  207.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
  208.   if (ret != 0)
  209.   {
  210.     return ret;
  211.   }
  212.   if (arg3 != expected_len)
  213.   {
  214.     return -1;
  215.   }
  216.   p_buf = vsf_sysutil_malloc((int) expected_len);
  217.   ret = ptrace_sandbox_get_buf(p_sandbox, arg2, expected_len, p_buf);
  218.   if (ret != 0)
  219.   {
  220.     vsf_sysutil_free(p_buf);
  221.     return -2;
  222.   }
  223.   p_sockaddr = (struct sockaddr*) p_buf;
  224.   if (p_sockaddr->sa_family != expected_family)
  225.   {
  226.     vsf_sysutil_free(p_buf);
  227.     return -3;
  228.   }
  229.   if (expected_family == AF_INET)
  230.   {
  231.     struct sockaddr_in* p_sockaddr_in = (struct sockaddr_in*) p_sockaddr;
  232.     vsf_sysutil_sockaddr_alloc_ipv4(&p_sockptr);
  233.     vsf_sysutil_sockaddr_set_ipv4addr(p_sockptr,
  234.                                       (const unsigned char*)
  235.                                           &p_sockaddr_in->sin_addr);
  236.   }
  237.   else
  238.   {
  239.     struct sockaddr_in6* p_sockaddr_in6 = (struct sockaddr_in6*) p_sockaddr;
  240.     vsf_sysutil_sockaddr_alloc_ipv6(&p_sockptr);
  241.     vsf_sysutil_sockaddr_set_ipv6addr(p_sockptr,
  242.                                       (const unsigned char*)
  243.                                           &p_sockaddr_in6->sin6_addr);
  244.   }
  245.   if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_sockptr))
  246.   {
  247.     vsf_sysutil_free(p_buf);
  248.     return -4;
  249.   }
  250.   vsf_sysutil_free(p_buf);
  251.   return 0;
  252. }
  253. static int
  254. getsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  255. {
  256.   int ret;
  257.   unsigned long arg2;
  258.   unsigned long arg3;
  259.   (void) p_arg;
  260.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  261.   if (ret != 0)
  262.   {
  263.     return ret;
  264.   }
  265.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
  266.   if (ret != 0)
  267.   {
  268.     return ret;
  269.   }
  270.   if (arg2 != SOL_SOCKET || arg3 != SO_ERROR)
  271.   {
  272.     return -1;
  273.   }
  274.   return 0;
  275. }
  276. static int
  277. setsockopt_validator(struct pt_sandbox* p_sandbox, void* p_arg)
  278. {
  279.   int ret;
  280.   unsigned long arg2;
  281.   unsigned long arg3;
  282.   (void) p_arg;
  283.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 1, &arg2);
  284.   if (ret != 0)
  285.   {
  286.     return ret;
  287.   }
  288.   ret = ptrace_sandbox_get_socketcall_arg(p_sandbox, 2, &arg3);
  289.   if (ret != 0)
  290.   {
  291.     return ret;
  292.   }
  293.   if (arg2 == SOL_SOCKET)
  294.   {
  295.     if (arg3 != SO_KEEPALIVE &&
  296.         arg3 != SO_REUSEADDR &&
  297.         arg3 != SO_OOBINLINE &&
  298.         arg3 != SO_LINGER)
  299.     {
  300.       return -1;
  301.     }
  302.   }
  303.   else if (arg2 == IPPROTO_TCP)
  304.   {
  305.     if (arg3 != TCP_NODELAY)
  306.     {
  307.       return -2;
  308.     }
  309.   }
  310.   else if (arg2 == IPPROTO_IP)
  311.   {
  312.     if (arg3 != IP_TOS)
  313.     {
  314.       return -3;
  315.     }
  316.   }
  317.   else
  318.   {
  319.     return -4;
  320.   }
  321.   return 0;
  322. }