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

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * postprivparent.c
  6.  *
  7.  * This file contains all privileged parent services offered after logging
  8.  * in. This includes e.g. chown() of uploaded files, issuing of port 20
  9.  * sockets.
  10.  */
  11. #include "postprivparent.h"
  12. #include "session.h"
  13. #include "privops.h"
  14. #include "privsock.h"
  15. #include "utility.h"
  16. #include "tunables.h"
  17. #include "defs.h"
  18. #include "sysutil.h"
  19. #include "str.h"
  20. #include "secutil.h"
  21. #include "sysstr.h"
  22. #include "sysdeputil.h"
  23. static void minimize_privilege(struct vsf_session* p_sess);
  24. static void process_post_login_req(struct vsf_session* p_sess);
  25. static void cmd_process_chown(struct vsf_session* p_sess);
  26. static void cmd_process_get_data_sock(struct vsf_session* p_sess);
  27. static void cmd_process_pasv_cleanup(struct vsf_session* p_sess);
  28. static void cmd_process_pasv_active(struct vsf_session* p_sess);
  29. static void cmd_process_pasv_listen(struct vsf_session* p_sess);
  30. static void cmd_process_pasv_accept(struct vsf_session* p_sess);
  31. void
  32. vsf_priv_parent_postlogin(struct vsf_session* p_sess)
  33. {
  34.   minimize_privilege(p_sess);
  35.   /* We're still here... */
  36.   while (1)
  37.   {
  38.     process_post_login_req(p_sess);
  39.   }
  40. }
  41. static void
  42. process_post_login_req(struct vsf_session* p_sess)
  43. {
  44.   char cmd;
  45.   /* Blocks */
  46.   cmd = priv_sock_get_cmd(p_sess->parent_fd);
  47.   if (tunable_chown_uploads && cmd == PRIV_SOCK_CHOWN)
  48.   {
  49.     cmd_process_chown(p_sess);
  50.   }
  51.   else if (cmd == PRIV_SOCK_GET_DATA_SOCK)
  52.   {
  53.     cmd_process_get_data_sock(p_sess);
  54.   }
  55.   else if (cmd == PRIV_SOCK_PASV_CLEANUP)
  56.   {
  57.     cmd_process_pasv_cleanup(p_sess);
  58.   }
  59.   else if (cmd == PRIV_SOCK_PASV_ACTIVE)
  60.   {
  61.     cmd_process_pasv_active(p_sess);
  62.   }
  63.   else if (cmd == PRIV_SOCK_PASV_LISTEN)
  64.   {
  65.     cmd_process_pasv_listen(p_sess);
  66.   }
  67.   else if (cmd == PRIV_SOCK_PASV_ACCEPT)
  68.   {
  69.     cmd_process_pasv_accept(p_sess);
  70.   }
  71.   else
  72.   {
  73.     die("bad request in process_post_login_req");
  74.   }
  75. }
  76. static void
  77. minimize_privilege(struct vsf_session* p_sess)
  78. {
  79.   /* So, we logged in and forked a totally unprivileged child. Our job
  80.    * now is to minimize the privilege we need in order to act as a helper
  81.    * to the child.
  82.    */
  83.   if (!p_sess->is_anonymous && tunable_session_support)
  84.   {
  85.     /* Need to hang around to update logs, utmp, wtmp etc. on logout.
  86.      * Need to keep privs to do this. */
  87.     return;
  88.   }
  89.   {
  90.     unsigned int caps = 0;
  91.     struct mystr user_str = INIT_MYSTR;
  92.     struct mystr dir_str = INIT_MYSTR;
  93.     str_alloc_text(&user_str, tunable_nopriv_user);
  94.     str_alloc_text(&dir_str, tunable_secure_chroot_dir);
  95.     if (tunable_chown_uploads)
  96.     {
  97.       caps |= kCapabilityCAP_CHOWN;
  98.     }
  99.     if (tunable_connect_from_port_20)
  100.     {
  101.       caps |= kCapabilityCAP_NET_BIND_SERVICE;
  102.     }
  103.     vsf_secutil_change_credentials(&user_str, &dir_str, 0, caps,
  104.                                    VSF_SECUTIL_OPTION_CHROOT);
  105.     str_free(&user_str);
  106.     str_free(&dir_str);
  107.   }
  108. }
  109. static void
  110. cmd_process_chown(struct vsf_session* p_sess)
  111. {
  112.   int the_fd = priv_sock_recv_fd(p_sess->parent_fd);
  113.   vsf_privop_do_file_chown(p_sess, the_fd);
  114.   vsf_sysutil_close(the_fd);
  115.   priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
  116. }
  117. static void
  118. cmd_process_get_data_sock(struct vsf_session* p_sess)
  119. {
  120.   unsigned short port = (unsigned short) priv_sock_get_int(p_sess->parent_fd);
  121.   int sock_fd = vsf_privop_get_ftp_port_sock(p_sess, port);
  122.   if (sock_fd == -1)
  123.   {
  124.     priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);
  125.     return;
  126.   }
  127.   priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
  128.   priv_sock_send_fd(p_sess->parent_fd, sock_fd);
  129.   vsf_sysutil_close(sock_fd);
  130. }
  131. static void
  132. cmd_process_pasv_cleanup(struct vsf_session* p_sess)
  133. {
  134.   vsf_privop_pasv_cleanup(p_sess);
  135.   priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
  136. }
  137. static void
  138. cmd_process_pasv_active(struct vsf_session* p_sess)
  139. {
  140.   int active = vsf_privop_pasv_active(p_sess);
  141.   priv_sock_send_int(p_sess->parent_fd, active);
  142. }
  143. static void
  144. cmd_process_pasv_listen(struct vsf_session* p_sess)
  145. {
  146.   unsigned short port = vsf_privop_pasv_listen(p_sess);
  147.   priv_sock_send_int(p_sess->parent_fd, port);
  148. }
  149. static void
  150. cmd_process_pasv_accept(struct vsf_session* p_sess)
  151. {
  152.   int fd = vsf_privop_accept_pasv(p_sess);
  153.   if (fd < 0)
  154.   {
  155.     priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);
  156.     priv_sock_send_int(p_sess->parent_fd, fd);
  157.     return;
  158.   }
  159.   priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
  160.   priv_sock_send_fd(p_sess->parent_fd, fd);
  161.   vsf_sysutil_close(fd);
  162. }